zoem-11-166/0000777000402500021140000000000011576212300007554 500000000000000zoem-11-166/README0000644000402500021140000000342311251426055010356 00000000000000# $Id: README,v 1.4 2002/12/18 13:40:14 flux Exp $ Zoem is an interpreter for an interpretive language which is called, as things go, zoem. From the Zoem User Manual: Zoem is an interpretive macro language with substantial facilities for programming. It supports a two-stage process, consisting of macro interpretation (featuring inside-out evaluation if needed), followed by a simple and powerful application of stream character filtering. Its syntax is remindful of \it{TeX}'s, it has dictionary stacks like \it{PostScript}, and various resemblances to \it{m4} and \it{info}. It has interfaces to modules making life easy \- counters, references, arithmetic, multi-dimensional data storage, input/output operations, regular expressions, and system commands. Zoem is used for creating extendible dummy mark-up languages and mapping those to real mark-up languages. The dummy languages have all the power of the zoem primitives available to them. A prime application is the creation of little mark-up languages that allow easy preparation of documents for use with different devices. Examples are the PUD \bf{faq} language and the PUD \bf{man} language, both of which can be used to generate troff output and html output. PUD stands for Portable Unix Documentation and is shipped with Aephea. Aephea itself is an abstraction layer for creating concise and maintainable HTML documents. The version tag, which is of the form dd-ddd, encodes the year and day in year in which the distribution was made. So 02-058 encodes the 58-th day of the year 2002. See LICENSE for copyright and licensing, see THANKS for contributors, see INSTALL for generic installation instructions. zoem-11-166/acinclude.m40000644000402500021140000003526611444411522011676 00000000000000 ## va_copy check ## dnl Available from the GNU Autoconf Macro Archive at: dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html dnl AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthread or # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no) if test x"$acx_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: threads are created detached by default # and the JOINABLE attribute has a nonstandard name (UNDETACHED). AC_MSG_CHECKING([for joinable pthread attribute]) AC_TRY_LINK([#include ], [int attr=PTHREAD_CREATE_JOINABLE;], ok=PTHREAD_CREATE_JOINABLE, ok=unknown) if test x"$ok" = xunknown; then AC_TRY_LINK([#include ], [int attr=PTHREAD_CREATE_UNDETACHED;], ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) fi if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, [Define to the necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_RESULT(${ok}) if test x"$ok" = xunknown; then AC_MSG_WARN([we do not know how to create joinable pthreads]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";; *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with cc_r AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl ACX_PTHREAD ## va_copy check ## dnl ## dnl ## NAME: dnl ## AC_CHECK_VA_COPY -- Check for C99 va_copy dnl ## dnl ## COPYRIGHT dnl ## Copyright (c) 2006 Ralf S. Engelschall dnl ## dnl ## DESCRIPTION: dnl ## This macro checks for C99 va_copy() implementation and dnl ## provides fallback implementation if neccessary. Notice: this dnl ## check is rather complex because first because we really have dnl ## to try various possible implementations in sequence and dnl ## second, we cannot define a macro in config.h with parameters dnl ## directly. dnl ## dnl ## USAGE: dnl ## configure.in: dnl ## AC_CHECK_VA_COPY dnl ## foo.c: dnl ## #include "config.h" dnl ## [...] dnl ## va_copy(d,s) dnl ## dnl # test program for va_copy() implementation changequote(<<,>>) m4_define(__va_copy_test, <<[ #include #include #include #define DO_VA_COPY(d, s) $1 void test(char *str, ...) { va_list ap, ap2; int i; va_start(ap, str); DO_VA_COPY(ap2, ap); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } DO_VA_COPY(ap, ap2); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } va_end(ap); } int main(int argc, char *argv[]) { test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9); exit(0); } ]>>) changequote([,]) dnl # test driver for va_copy() implementation m4_define(__va_copy_check, [ AH_VERBATIM($1, [/* Predefined possible va_copy() implementation (id: $1) */ #define __VA_COPY_USE_$1(d, s) $2]) if test ".$ac_cv_va_copy" = .; then AC_TRY_RUN(__va_copy_test($2), [ac_cv_va_copy="$1"]) fi ]) dnl # Autoconf check for va_copy() implementation checking AC_DEFUN([AC_CHECK_VA_COPY],[ dnl # provide Autoconf display check message AC_MSG_CHECKING(for va_copy() function) dnl # check for various implementations in priorized sequence AC_CACHE_VAL(ac_cv_va_copy, [ ac_cv_va_copy="" dnl # 1. check for standardized C99 macro __va_copy_check(C99, [va_copy((d), (s))]) dnl # 2. check for alternative/deprecated GCC macro __va_copy_check(GCM, [VA_COPY((d), (s))]) dnl # 3. check for internal GCC macro (high-level define) __va_copy_check(GCH, [__va_copy((d), (s))]) dnl # 4. check for internal GCC macro (built-in function) __va_copy_check(GCB, [__builtin_va_copy((d), (s))]) dnl # 5. check for assignment approach (assuming va_list is a struct) __va_copy_check(ASS, [do { (d) = (s); } while (0)]) dnl # 6. check for assignment approach (assuming va_list is a pointer) __va_copy_check(ASP, [do { *(d) = *(s); } while (0)]) dnl # 7. check for memory copying approach (assuming va_list is a struct) __va_copy_check(CPS, [memcpy((void *)&(d), (void *)&(s)), sizeof((s))]) dnl # 8. check for memory copying approach (assuming va_list is a pointer) __va_copy_check(CPP, [memcpy((void *)(d), (void *)(s)), sizeof(*(s))]) if test ".$ac_cv_va_copy" = .; then AC_ERROR([no working implementation found]) fi ]) dnl # optionally activate the fallback implementation if test ".$ac_cv_va_copy" = ".C99"; then AC_DEFINE(HAVE_VA_COPY, 1, [Define if va_copy() macro exists (and no fallback implementation is required)]) fi dnl # declare which fallback implementation to actually use AC_DEFINE_UNQUOTED([__VA_COPY_USE], [__VA_COPY_USE_$ac_cv_va_copy], [Define to id of used va_copy() implementation]) dnl # provide activation hook for fallback implementation AH_VERBATIM([__VA_COPY_ACTIVATION], [/* Optional va_copy() implementation activation */ #ifndef HAVE_VA_COPY #define va_copy(d, s) __VA_COPY_USE(d, s) #define HAVE_VA_COPY 1 #endif ]) dnl # provide Autoconf display result message if test ".$ac_cv_va_copy" = ".C99"; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no (using fallback implementation)]) fi ]) ## Referenceable va_list ## # http://autoconf-archive.cryp.to/ax_c_referenceable_passed_va_list.html AC_DEFUN([AX_C_REFERENCEABLE_PASSED_VA_LIST], [ AC_CACHE_CHECK([whether f(va_list va){ &va; } works as expected], [ax_cv_c_referenceable_passed_va_list], [AC_LINK_IFELSE([[ #include volatile va_list g_va; void vf(va_list callee_va) { /* typeof(callee_va) differs from typeof(caller_va) by a compiler trick, if * va_list is implemented as an array. On such environment, this copy * operation fails. */ g_va = callee_va; } void f(int last, ...) { va_list caller_va; va_start(caller_va, last); vf(caller_va); /* passed as &caller_va[0] if va_list is an array type */ va_end(caller_va); } int main(int argc, char *argv[]) { f(0xdeadbeef, 0xfedbeef, 0xfeedee); return 0; } ]], [ax_cv_c_referenceable_passed_va_list=yes], [ax_cv_c_referenceable_passed_va_list=no])]) if test "x$ax_cv_c_referenceable_passed_va_list" = xyes; then AC_DEFINE([HAVE_REFERENCEABLE_PASSED_VA_LIST], [1], [Define to 1 if f(va_list va){ &va; } works as expected.]) fi ]) AC_DEFUN([AC_LIB_READLINE], [ AC_CACHE_CHECK([for the readline library], ac_cv_lib_readline, [ ac_cv_lib_readline="no" ORIG_LIBS=$LIBS LIBS="$ORIG_LIBS -lreadline -ltermcap" AC_TRY_LINK_FUNC(readline, ac_cv_lib_readline="yes") if test "$ac_cv_lib_readline" = "no"; then LIBS=$ORIG_LIBS fi ]) enable_readline="no" if test "$ac_cv_lib_readline" = "yes"; then AC_CHECK_HEADERS(readline.h readline/readline.h) AC_CACHE_CHECK([whether readline supports history], ac_cv_lib_readline_history, [ ac_cv_lib_readline_history="no" AC_TRY_LINK_FUNC(add_history, ac_cv_lib_readline_history="yes") ]) if test "$ac_cv_lib_readline_history" = "yes"; then AC_CHECK_HEADERS(history.h readline/history.h) AC_CACHE_CHECK([whether readline supports completion], ac_cv_lib_readline_completion, [ ac_cv_lib_readline_completion="no" AC_TRY_LINK_FUNC(rl_completion_matches, ac_cv_lib_readline_completion="yes") ]) if test "$ac_cv_lib_readline_completion" = "yes"; then enable_readline="yes" fi fi else AC_MSG_RESULT([readline or termcap library is missing]) fi ]) AC_DEFUN([AC_WITH_READLINE], [ AC_ARG_WITH(readline, [ --with-readline=DIR Readline installation directory], with_readline=$withval) if test "$with_readline" != ""; then CPPFLAGS="-I$with_readline/include $CPPFLAGS" LIBS="-L$with_readline/lib $LIBS" fi ]) AC_DEFUN([AC_MMX_OPTION_READLINE], [ AC_ARG_ENABLE(readline, AC_HELP_STRING( [--enable-readline], [use the readline library [[yes]]]), [], [enable_readline="yes"]) if test "$enable_readline" = "yes"; then AC_WITH_READLINE AC_LIB_READLINE fi if test "$enable_readline" = "no"; then AC_MSG_RESULT([disabling readline]) AC_DEFINE(HAVE_READLINE, 0, [Define if you have the readline library]) else AC_MSG_RESULT([enabling readline]) AC_DEFINE(HAVE_READLINE, 1, [Define if you have the readline library]) fi AM_CONDITIONAL([READLINE_OPT], [test "$enable_readline" = "yes"]) ]) zoem-11-166/configure.ac0000644000402500021140000000567011576203373012000 00000000000000# configure.ac - generated from configure.ac.in by setversion. do not edit # configure.ac, but edit the master. # $Id: configure.ac.in,v 1.15 2004/06/09 16:42:58 flux Exp $ ## are we using AC_CONFIG_HEADERS? ## in http://www.gnu.org/software/autoconf/manual/autoconf.html#Writing-Autoconf-Input ## it is suggested that this is required to output config.h ## we are using AM_CONFIG_HEADER instead. How does this work? # Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) AC_INIT(zoem, 11-166, stijn@micans.org) PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION AC_CONFIG_SRCDIR([src/segment.c]) AM_INIT_AUTOMAKE($PACKAGE, $VERSION) AC_CONFIG_HEADERS(config.h) # AC_CONFIG_HEADERS([config.h]) # add a `--enable-maintainer-mode' option to `configure'; `maintainer-only' rules turned off by # default in Makefile.in's AM_MAINTAINER_MODE AC_SUBST(PACKAGE) AC_SUBST(VERSION) AC_ARG_WITH( includepath, AC_HELP_STRING( [ --with-includepath=DIR ], [ a colon separated list of directories where to look for definition files. It is overridden by the environment variable ZOEMSEARCHPATH, if set. The default is PREFIX/share/aephea. If Aephea files are installed e.g. as /opt/aephea/aephea/simpledocument.zmm /opt/aephea/pud/man.zmm then pass --with-includepath=/opt/aephea. If aephea is installed with the same PREFIX as zoem, nothing need be done. ] ), [ if test "x$prefix" != xNONE; then ac_cv_use_includepath=$withval:$prefix/share/aephea else ac_cv_use_includepath=$withval:/usr/local/share/aephea fi ], [ if test "x$prefix" != xNONE; then ac_cv_use_includepath=$prefix/share/aephea else ac_cv_use_includepath=/usr/local/share/aephea fi ] ) AC_CACHE_CHECK( Include path(s) to add, ac_cv_use_includepath, [ if test "x$prefix" != xNONE; then ac_cv_use_includepath=$prefix/share/aephea else ac_cv_use_includepath=/usr/local/share/aephea fi ] ) AC_DEFINE_UNQUOTED(INCLUDEPATH, $ac_cv_use_includepath, [ where to look for zoem macro files ]) AC_SUBST(ac_cv_use_includepath) # Checks for programs. AC_PROG_AWK AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_RANLIB # Checks for libraries. # Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS([fcntl.h float.h limits.h stdlib.h string.h ]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_PID_T # Checks for library functions. AC_FUNC_VPRINTF AC_FUNC_FORK AC_FUNC_MALLOC AC_FUNC_MEMCMP # AC_FUNC_REALLOC AC_MMX_OPTION_READLINE AC_CHECK_FUNCS([dup2 floor memset pow regcomp sqrt strchr strrchr strstr]) AC_CHECK_VA_COPY # AC_CONFIG_FILES([]) AC_OUTPUT([ Makefile doc/Makefile examples/Makefile src/Makefile util/Makefile ]) zoem-11-166/aclocal.m40000644000402500021140000010704611576203376011355 00000000000000# generated automatically by aclocal 1.11 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # This file 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. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],, [m4_warning([this file was generated for autoconf 2.65. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) # Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # # This file 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. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.11], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.11])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file 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. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 # Free Software Foundation, Inc. # # This file 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. # serial 9 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 # Free Software Foundation, Inc. # # This file 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. # serial 10 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. #serial 5 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2008, 2009 Free Software Foundation, Inc. # # This file 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. # serial 16 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES(OBJC)], [define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The `parallel-tests' driver may need to know about EXEEXT, so add the dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. # # This file 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. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file 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. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. # serial 5 # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless `enable' is passed literally. # For symmetry, `disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful (and sometimes confusing) to the casual installer], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. # # This file 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. # serial 4 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. # serial 6 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # # This file 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. # AM_PROG_MKDIR_P # --------------- # Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. # # This file 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. # serial 4 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 # Free Software Foundation, Inc. # # This file 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. # serial 5 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; esac # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file 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. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006, 2008 Free Software Foundation, Inc. # # This file 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. # serial 2 # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file 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. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([acinclude.m4]) zoem-11-166/Makefile.am0000644000402500021140000000130311251206247011524 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am,v 1.20 2004/06/24 11:43:11 flux Exp $ ## all-local: stamp-util ## stamp-util: ## ## do some magic to fiddle with util. util is in cvs in ../util/ , ## ## not in the zoem tree itself. ## for i in $(top_srcdir)/../util/*.h $(top_srcdir)/../util/*.c; do \ ## $(INSTALL_DATA) $$i $(top_srcdir)/util; \ ## done ## touch stamp-util maintainer-clean-local: -rm -f $(top_srcdir)/util/*.h $(top_srcdir)/util/*.c SUBDIRS = . util src doc examples VERSION = @VERSION@ configure.ac: configure.ac.in VERSION ./setversion EXTRA_DIST = configure.ac.in bootstrap setversion VERSION LICENSE TODO_DESIGN\ DESIGN zoem-11-166/Makefile.in0000644000402500021140000005265211576203400011550 00000000000000# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ 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 = : subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \ THANKS TODO depcomp install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_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 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 dist dist-all distcheck ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d "$(distdir)" \ || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr "$(distdir)"; }; } 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" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_cv_use_includepath = @ac_cv_use_includepath@ 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_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . util src doc examples EXTRA_DIST = configure.ac.in bootstrap setversion VERSION LICENSE TODO_DESIGN\ DESIGN all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 # 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): @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//`; \ list='$(SUBDIRS)'; 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" $(RECURSIVE_CLEAN_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && 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 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) config.h.in $(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) config.h.in $(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) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) config.h.in $(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" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @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 \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ 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 -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-lzma: distdir tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma $(am__remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lzma*) \ unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @$(am__cd) '$(distuninstallcheck_dir)' \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ ctags-recursive install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-generic \ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \ distclean distclean-generic distclean-hdr distclean-tags \ distcleancheck distdir distuninstallcheck 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 installdirs-am maintainer-clean \ maintainer-clean-generic maintainer-clean-local mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am maintainer-clean-local: -rm -f $(top_srcdir)/util/*.h $(top_srcdir)/util/*.c configure.ac: configure.ac.in VERSION ./setversion # 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: zoem-11-166/config.h.in0000644000402500021140000001203411576147633011533 00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Predefined possible va_copy() implementation (id: ASP) */ #define __VA_COPY_USE_ASP(d, s) do { *(d) = *(s); } while (0) /* Predefined possible va_copy() implementation (id: ASS) */ #define __VA_COPY_USE_ASS(d, s) do { (d) = (s); } while (0) /* Predefined possible va_copy() implementation (id: C99) */ #define __VA_COPY_USE_C99(d, s) va_copy((d), (s)) /* Predefined possible va_copy() implementation (id: CPP) */ #define __VA_COPY_USE_CPP(d, s) memcpy((void *)(d), (void *)(s)), sizeof(*(s)) /* Predefined possible va_copy() implementation (id: CPS) */ #define __VA_COPY_USE_CPS(d, s) memcpy((void *)&(d), (void *)&(s)), sizeof((s)) /* Predefined possible va_copy() implementation (id: GCB) */ #define __VA_COPY_USE_GCB(d, s) __builtin_va_copy((d), (s)) /* Predefined possible va_copy() implementation (id: GCH) */ #define __VA_COPY_USE_GCH(d, s) __va_copy((d), (s)) /* Predefined possible va_copy() implementation (id: GCM) */ #define __VA_COPY_USE_GCM(d, s) VA_COPY((d), (s)) /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ #undef HAVE_DOPRNT /* Define to 1 if you have the `dup2' function. */ #undef HAVE_DUP2 /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the header file. */ #undef HAVE_FLOAT_H /* Define to 1 if you have the `floor' function. */ #undef HAVE_FLOOR /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the header file. */ #undef HAVE_HISTORY_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #undef HAVE_MALLOC /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memset' function. */ #undef HAVE_MEMSET /* Define to 1 if you have the `pow' function. */ #undef HAVE_POW /* Define if you have the readline library */ #undef HAVE_READLINE /* Define to 1 if you have the header file. */ #undef HAVE_READLINE_H /* Define to 1 if you have the header file. */ #undef HAVE_READLINE_HISTORY_H /* Define to 1 if you have the header file. */ #undef HAVE_READLINE_READLINE_H /* Define to 1 if you have the `regcomp' function. */ #undef HAVE_REGCOMP /* Define to 1 if you have the `sqrt' function. */ #undef HAVE_SQRT /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strrchr' function. */ #undef HAVE_STRRCHR /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define if va_copy() macro exists (and no fallback implementation is required) */ #undef HAVE_VA_COPY /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* Define to 1 if you have the header file. */ #undef HAVE_VFORK_H /* Define to 1 if you have the `vprintf' function. */ #undef HAVE_VPRINTF /* Define to 1 if `fork' works. */ #undef HAVE_WORKING_FORK /* Define to 1 if `vfork' works. */ #undef HAVE_WORKING_VFORK /* where to look for zoem macro files */ #undef INCLUDEPATH /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Version number of package */ #undef VERSION /* Optional va_copy() implementation activation */ #ifndef HAVE_VA_COPY #define va_copy(d, s) __VA_COPY_USE(d, s) #define HAVE_VA_COPY 1 #endif /* Define to id of used va_copy() implementation */ #undef __VA_COPY_USE /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to rpl_malloc if the replacement function should be used. */ #undef malloc /* Define to `int' if does not define. */ #undef pid_t /* Define as `fork' if `vfork' does not work. */ #undef vfork zoem-11-166/configure0000755000402500021140000060457611576203401011423 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65 for zoem 11-166. # # Report bugs to . # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and stijn@micans.org $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='zoem' PACKAGE_TARNAME='zoem' PACKAGE_VERSION='11-166' PACKAGE_STRING='zoem 11-166' PACKAGE_BUGREPORT='stijn@micans.org' PACKAGE_URL='' ac_unique_file="src/segment.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS READLINE_OPT_FALSE READLINE_OPT_TRUE LIBOBJS EGREP GREP CPP RANLIB LN_S am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC ac_cv_use_includepath MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_maintainer_mode with_includepath enable_dependency_tracking enable_readline with_readline ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error "unrecognized option: \`$ac_option' Try \`$0 --help' for more information." ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures zoem 11-166 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/zoem] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of zoem 11-166:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-readline use the readline library [[yes]] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-includepath=DIR a colon separated list of directories where to look for definition files. It is overridden by the environment variable ZOEMSEARCHPATH, if set. The default is PREFIX/share/aephea. If Aephea files are installed e.g. as /opt/aephea/aephea/simpledocument.zmm /opt/aephea/pud/man.zmm then pass --with-includepath=/opt/aephea. If aephea is installed with the same PREFIX as zoem, nothing need be done. --with-readline=DIR Readline installation directory Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF zoem configure 11-166 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( cat <<\_ASBOX ## ------------------------------- ## ## Report this to stijn@micans.org ## ## ------------------------------- ## _ASBOX ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_mongrel # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_compile # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_type # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by zoem $as_me 11-166, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION am__api_version='1.11' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do for ac_t in install-sh install.sh shtool; do if test -f "$ac_dir/$ac_t"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/$ac_t -c" break 2 fi done done if test -z "$ac_aux_dir"; then as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; esac # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi test "$2" = conftest.file ) then # Ok. : else as_fn_error "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if test "${ac_cv_path_mkdir+set}" = set; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AWK+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE=$PACKAGE VERSION=$VERSION cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' ac_config_headers="$ac_config_headers config.h" # AC_CONFIG_HEADERS([config.h]) # add a `--enable-maintainer-mode' option to `configure'; `maintainer-only' rules turned off by # default in Makefile.in's { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE # Check whether --with-includepath was given. if test "${with_includepath+set}" = set; then : withval=$with_includepath; if test "x$prefix" != xNONE; then ac_cv_use_includepath=$withval:$prefix/share/aephea else ac_cv_use_includepath=$withval:/usr/local/share/aephea fi else if test "x$prefix" != xNONE; then ac_cv_use_includepath=$prefix/share/aephea else ac_cv_use_includepath=/usr/local/share/aephea fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking Include path(s) to add" >&5 $as_echo_n "checking Include path(s) to add... " >&6; } if test "${ac_cv_use_includepath+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "x$prefix" != xNONE; then ac_cv_use_includepath=$prefix/share/aephea else ac_cv_use_includepath=/usr/local/share/aephea fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_use_includepath" >&5 $as_echo "$ac_cv_use_includepath" >&6; } cat >>confdefs.h <<_ACEOF #define INCLUDEPATH $ac_cv_use_includepath _ACEOF # Checks for programs. for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AWK+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "no acceptable C compiler found in \$PATH See \`config.log' for more details." "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { as_fn_set_status 77 as_fn_error "C compiler cannot create executables See \`config.log' for more details." "$LINENO" 5; }; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot compute suffix of object files: cannot compile See \`config.log' for more details." "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi # Checks for libraries. # Checks for header files. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if test "${ac_cv_path_GREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if test "${ac_cv_path_EGREP+set}" = set; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 $as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } if test "${ac_cv_header_sys_wait_h+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main () { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_sys_wait_h=yes else ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 $as_echo "$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then $as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in fcntl.h float.h limits.h stdlib.h string.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Checks for typedefs, structures, and compiler characteristics. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if test "${ac_cv_c_const+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset cs; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = x""yes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi # Checks for library functions. for ac_func in vprintf do : ac_fn_c_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf" if test "x$ac_cv_func_vprintf" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VPRINTF 1 _ACEOF ac_fn_c_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt" if test "x$ac_cv_func__doprnt" = x""yes; then : $as_echo "#define HAVE_DOPRNT 1" >>confdefs.h fi fi done for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" eval as_val=\$$as_ac_var if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if test "${ac_cv_func_fork_works+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if test "${ac_cv_func_vfork_works+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 $as_echo_n "checking for working memcmp... " >&6; } if test "${ac_cv_func_memcmp_working+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_memcmp_working=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = '\100', c1 = '\200', c2 = '\201'; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) return 1; /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) return 1; } return 0; } ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_memcmp_working=yes else ac_cv_func_memcmp_working=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 $as_echo "$ac_cv_func_memcmp_working" >&6; } test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in *" memcmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;; esac # AC_FUNC_REALLOC # Check whether --enable-readline was given. if test "${enable_readline+set}" = set; then : enableval=$enable_readline; else enable_readline="yes" fi if test "$enable_readline" = "yes"; then # Check whether --with-readline was given. if test "${with_readline+set}" = set; then : withval=$with_readline; with_readline=$withval fi if test "$with_readline" != ""; then CPPFLAGS="-I$with_readline/include $CPPFLAGS" LIBS="-L$with_readline/lib $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the readline library" >&5 $as_echo_n "checking for the readline library... " >&6; } if test "${ac_cv_lib_readline+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_lib_readline="no" ORIG_LIBS=$LIBS LIBS="$ORIG_LIBS -lreadline -ltermcap" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char readline (); int main () { return readline (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline="yes" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test "$ac_cv_lib_readline" = "no"; then LIBS=$ORIG_LIBS fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline" >&5 $as_echo "$ac_cv_lib_readline" >&6; } enable_readline="no" if test "$ac_cv_lib_readline" = "yes"; then for ac_header in readline.h readline/readline.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether readline supports history" >&5 $as_echo_n "checking whether readline supports history... " >&6; } if test "${ac_cv_lib_readline_history+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_lib_readline_history="no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char add_history (); int main () { return add_history (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline_history="yes" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_history" >&5 $as_echo "$ac_cv_lib_readline_history" >&6; } if test "$ac_cv_lib_readline_history" = "yes"; then for ac_header in history.h readline/history.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether readline supports completion" >&5 $as_echo_n "checking whether readline supports completion... " >&6; } if test "${ac_cv_lib_readline_completion+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_lib_readline_completion="no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char rl_completion_matches (); int main () { return rl_completion_matches (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_readline_completion="yes" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_completion" >&5 $as_echo "$ac_cv_lib_readline_completion" >&6; } if test "$ac_cv_lib_readline_completion" = "yes"; then enable_readline="yes" fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: readline or termcap library is missing" >&5 $as_echo "readline or termcap library is missing" >&6; } fi fi if test "$enable_readline" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabling readline" >&5 $as_echo "disabling readline" >&6; } $as_echo "#define HAVE_READLINE 0" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabling readline" >&5 $as_echo "enabling readline" >&6; } $as_echo "#define HAVE_READLINE 1" >>confdefs.h fi if test "$enable_readline" = "yes"; then READLINE_OPT_TRUE= READLINE_OPT_FALSE='#' else READLINE_OPT_TRUE='#' READLINE_OPT_FALSE= fi for ac_func in dup2 floor memset pow regcomp sqrt strchr strrchr strstr do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" eval as_val=\$$as_ac_var if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for va_copy() function" >&5 $as_echo_n "checking for va_copy() function... " >&6; } if test "${ac_cv_va_copy+set}" = set; then : $as_echo_n "(cached) " >&6 else ac_cv_va_copy="" if test ".$ac_cv_va_copy" = .; then if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run test program while cross compiling See \`config.log' for more details." "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #define DO_VA_COPY(d, s) va_copy((d), (s)) void test(char *str, ...) { va_list ap, ap2; int i; va_start(ap, str); DO_VA_COPY(ap2, ap); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } DO_VA_COPY(ap, ap2); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } va_end(ap); } int main(int argc, char *argv[]) { test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9); exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_va_copy="C99" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test ".$ac_cv_va_copy" = .; then if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run test program while cross compiling See \`config.log' for more details." "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #define DO_VA_COPY(d, s) VA_COPY((d), (s)) void test(char *str, ...) { va_list ap, ap2; int i; va_start(ap, str); DO_VA_COPY(ap2, ap); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } DO_VA_COPY(ap, ap2); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } va_end(ap); } int main(int argc, char *argv[]) { test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9); exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_va_copy="GCM" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test ".$ac_cv_va_copy" = .; then if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run test program while cross compiling See \`config.log' for more details." "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #define DO_VA_COPY(d, s) __va_copy((d), (s)) void test(char *str, ...) { va_list ap, ap2; int i; va_start(ap, str); DO_VA_COPY(ap2, ap); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } DO_VA_COPY(ap, ap2); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } va_end(ap); } int main(int argc, char *argv[]) { test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9); exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_va_copy="GCH" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test ".$ac_cv_va_copy" = .; then if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run test program while cross compiling See \`config.log' for more details." "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #define DO_VA_COPY(d, s) __builtin_va_copy((d), (s)) void test(char *str, ...) { va_list ap, ap2; int i; va_start(ap, str); DO_VA_COPY(ap2, ap); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } DO_VA_COPY(ap, ap2); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } va_end(ap); } int main(int argc, char *argv[]) { test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9); exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_va_copy="GCB" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test ".$ac_cv_va_copy" = .; then if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run test program while cross compiling See \`config.log' for more details." "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #define DO_VA_COPY(d, s) do { (d) = (s); } while (0) void test(char *str, ...) { va_list ap, ap2; int i; va_start(ap, str); DO_VA_COPY(ap2, ap); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } DO_VA_COPY(ap, ap2); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } va_end(ap); } int main(int argc, char *argv[]) { test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9); exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_va_copy="ASS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test ".$ac_cv_va_copy" = .; then if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run test program while cross compiling See \`config.log' for more details." "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #define DO_VA_COPY(d, s) do { *(d) = *(s); } while (0) void test(char *str, ...) { va_list ap, ap2; int i; va_start(ap, str); DO_VA_COPY(ap2, ap); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } DO_VA_COPY(ap, ap2); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } va_end(ap); } int main(int argc, char *argv[]) { test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9); exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_va_copy="ASP" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test ".$ac_cv_va_copy" = .; then if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run test program while cross compiling See \`config.log' for more details." "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #define DO_VA_COPY(d, s) memcpy((void *)&(d), (void *)&(s)) void test(char *str, ...) { va_list ap, ap2; int i; va_start(ap, str); DO_VA_COPY(ap2, ap); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } DO_VA_COPY(ap, ap2); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } va_end(ap); } int main(int argc, char *argv[]) { test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9); exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_va_copy="CPS" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test ".$ac_cv_va_copy" = .; then if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error "cannot run test program while cross compiling See \`config.log' for more details." "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #define DO_VA_COPY(d, s) memcpy((void *)(d), (void *)(s)) void test(char *str, ...) { va_list ap, ap2; int i; va_start(ap, str); DO_VA_COPY(ap2, ap); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } DO_VA_COPY(ap, ap2); for (i = 1; i <= 9; i++) { int k = (int)va_arg(ap, int); if (k != i) abort(); } va_end(ap); } int main(int argc, char *argv[]) { test("test", 1, 2, 3, 4, 5, 6, 7, 8, 9); exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_va_copy="CPP" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test ".$ac_cv_va_copy" = .; then as_fn_error "no working implementation found" "$LINENO" 5 fi fi if test ".$ac_cv_va_copy" = ".C99"; then $as_echo "#define HAVE_VA_COPY 1" >>confdefs.h fi cat >>confdefs.h <<_ACEOF #define __VA_COPY_USE __VA_COPY_USE_$ac_cv_va_copy _ACEOF if test ".$ac_cv_va_copy" = ".C99"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (using fallback implementation)" >&5 $as_echo "no (using fallback implementation)" >&6; } fi # AC_CONFIG_FILES([]) ac_config_files="$ac_config_files Makefile doc/Makefile examples/Makefile src/Makefile util/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${READLINE_OPT_TRUE}" && test -z "${READLINE_OPT_FALSE}"; then as_fn_error "conditional \"READLINE_OPT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error ERROR [LINENO LOG_FD] # --------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with status $?, using 1 if that was 0. as_fn_error () { as_status=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by zoem $as_me 11-166, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ zoem config.status 11-166 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "util/Makefile") CONFIG_FILES="$CONFIG_FILES util/Makefile" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || as_fn_error "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_t=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_t"; then break elif $ac_last_try; then as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || as_fn_error "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" } >"$tmp/config.h" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$tmp/config.h" "$ac_file" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit $? fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi zoem-11-166/AUTHORS0000644000402500021140000000040407575647730010565 00000000000000 zoem AUTHORS file $Id: AUTHORS,v 1.3 2002/12/11 14:46:48 flux Exp $ zoem the language and zoem the interpreter were written by Stijn van Dongen. zoem's build environment was created by Joost van Baal. See THANKS for names of other people who contributed. zoem-11-166/COPYING0000644000402500021140000004311011063270741010526 00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program 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 2 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. zoem-11-166/ChangeLog0000644000402500021140000013673211576103370011264 00000000000000 Wed, Jun 15 2011 * zoem-11-166 released. * The default search path was changed. The obsolete PREFIX/zoem/mac component was dropped, and PREFIX/aephea was added. Now, if zoem and aephea are both configured with the same prefix for installation (e.g. --prefix=/usr/local or --prefix=$HOME/local), then aephea include files will be found automatically by zoem. * set#3 can now splice into a variable (that is, the string refered to by a macro). This is achieved by pairing the respective keys {start} and {width} with appropriate values in the first argument to set#3. The start position is relative to an offst of zero, so \set{foo}{kaboom} \set{{start}{2}{width}{3}}{foo}{za} '\foo' yields 'kazam'. * The example zoem solution 8q2.azm to the N queens problem has been updated. It now pretty-prints asciific chess boards using the new splice mode to set#3. * Small documentation fixes. Wed, Sep 22 2010 * zoem-10-265 released. * In interactive mode zoem now utilise readline editing and history capababilities if available. This can be disabled completely at compile time or optionally at run time. * A new builtin macro seq#4 can be used as a simple type of for loop. \seq{i}{a}{b}{ ... } is equivalent to the pseudo code for (i=a;i, , and
. This is now specified in zoem as for example \<*meta>. The previously accepted syntax \ is now deprecated. The new syntax is more reasonable and makes it easier to recognize such special tags. * Zoem recognizes special classes of HTML/XML tags that do not have an associated close tag. For now these are tags that start with '!' or '?'. Previously accepted syntax such as \ is deprecated and is now simply written \. * The read routines now ignore nul bytes in files, improving zoem's robustness. It no longer yields unpredictable results on files with embedded nul bytes. Fri, Sep 5 2008 * zoem-08-248 released. * A bug manifested itself on powerpc + linux in the form of a crash, resulting from using vsnprintf repeatedly without sufficient corresponding va_start and va_end invocations. On some other platforms this bug would manifest itself as a mysterious zoem syntax error due to heap corruption. Fixed. Thanks to Philipp Benner, Tobias Quathamer, and Joost van Baal for bug reports. * Two modes for the defined#2 primitive have been renamed. "prim" has become "primitive" and "alias" has become "builtin", in line with zoem nomenclature and documentation. This change is backwards incompatible, but unlikely to affect anyone. * Option -ndollar was not working. fixed. Thu, Nov 29 2007 * zoem-07-333 released. * SYNOPSIS A bug in set#3 was removed, and two directives were added, namely batch definitions and a more legible way of appending to keys (see below). Keys local to environments (aka dollar keys) can now be defined using the same signature as when invoked, e.g. \begin{env}{{$k1}{v1}{$k2}{v2}}. This release also continues the focus on retiring what little special case syntax still exists. The format#2 specification syntax has been reworked (in an incompatible way) into a standard and extensible key-value syntax (see below). The format#2 implementation was redone and several new format#2 directives were added. xml/html syntactic sugar now stops introducing whitespace formatting when so instructed with the at directive \@{\w}. * Fixed bug in set#3 where usage of the {if} or {unless} directive corrupts state when combined with the {modes}{x} directive. * xml syntactic sugar cubes now obey the device scope \w directive. This means that xml elements, in the scope of an at directive \@{\w} no longer introduce white-space. This only affects the formatting of the XML/HTML code itself. This is for example useful when creating
 elements.

   *  The set#3 {modes} directive now accepts a v (for vararg mode)
      where a batch of key-value pairs can be defined within a single set#3
      invocation. This may improve the readability of resource files
      containing many definitions. Example:

         \set{{modes}{vw}}{}{
            {is_last}   {0}
            {ctrprev}   {0}
            {ctrnow}    {1}
         }

   *  Introduced append mode in set#3:
         \set{foo}{bar}
         \set{{modes}{a}}{foo}{bar}
      sets foo to barbar.

      append#2 is an alias for \set{{modes}{a}}{\1}{\2}
      appendx#2 is an alias for \set{{modes}{ax}}{\1}{\2}

      Hence append#2 appends to keys without expanding and appendx#2 appends
      to keys after expanding the to be appended text.
      Keys that are not defined when appended to will first be instantiated
      with an empty string.

   *  Keys local to environments (started by \begin#2) can now
      be defined using the same signature as used when invoking them, i.e.
      \begin{env}{{$foo}{bar}} as well as \begin{env}{{foo}{bar}}.

   *  Some bugs were found and removed in the format#2 implementation.

   *  format#2 has acquired a reuse mode where a format specification
      can be be reused a number of times or exhaust all arguments (see below).
      It has also acquired the 'border' directive for adding constant strings
      to the left and right of the formatted units.

   *  The tr#2 specification language is now also described in zoem(1), the manual
      page of the interpreter. The idea is that all - as few as possible -
      special purpose sub-languages will be described in there for ease of
      reference.

   *  The unwieldy format#2 specification language has been redefined to
      follow standard zoem syntax using keys and vararg value lists.  It is
      more verbose, but also more robust, compatibly extensible, powerful, and
      more easily understandable. As an example one now writes

      \format{
         %{{padding}{-=-_}
           {delimit}{ }
           {align}{left}
           {length}{length}
           {double}{{{arg}{foo}}}
           {width}{40}
          }%{
            {align}{right}
            {width}{40}
          }
      }{
         {arg1}{arg2}
      }

      rather than

      \format{%~{-=-_}{ }<40*{length}{foo}.%>40.}{
         {arg1}{arg2}
      }

      Formerly a format specifier was enclosed inbetween '%' and '.' . It
      interpreted special characters '<', '>', and '=', as well as the special
      characters '@', '*', '~' each of which had to be followed by two blocks.
      The same syntax is now obtained by a more customary key-value structure
      encoded as a zoem vararg.

      format#2 accepts new directives {border}{{left}{right}},
      {delimit}{{left}{right}}, {double}{{[{key}{value}]*}}, and
      {reuse}{|*}.

      {delimit} parameters decorate the formatted argument on the sides, and
      participate in the computations involving width, alignment and padding.
      There is no padding inbetween delimiters and the argument to be
      formatted.

      {border} parameters decorate the entire formatted product and do not
      participate in aforementioned computations. Padding is computed and
      produced before the borders are added.

      {double} can be used have the length computations performed on
      fake parameters. This can be useful when certain formatting
      elements need to be present in the true parameters.

      {reuse}{} will reuse the current specification  times,
      {reuse}{*} will reuse it until all arguments are exhausted. Thus

      \format{%{{align}{right}{width}{10}{reuse}{*}{padding}{{'}{}}}}{
         {beauty}{lies}{in}{the}{eye}{of}{the}{beholder}
      }
      \textmap{{repeat}{8}}{1234567890}

      results in

''''beauty''''''lies''''''''in'''''''the'''''''eye''''''''of'''''''the''beholder
12345678901234567890123456789012345678901234567890123456789012345678901234567890


Fri, Nov 9 2007

   *  zoem-07-313 released.

   *  \set{''foo}{bar} now works. It sets a key in the bottom (global)
      user dictionary. Same semantics as \set{{modes}{g}}{foo}{bar}.

   *  \undef#1 now checks whether its argument is a valid key signature.

   *  \undef{''foo} now works.

   *  Streamlined the error-processing part of the code.

   *  Added \textmap{{repeat}{}}{} mode. This results in 
       times repeated.  is evaluated before use.

   *  The special magic comment sequences
         \:/   delete rest of line including newline
         \:!   replace by '\' (for quoting zoem comments)

      are now deprecated (but still supported). Preferably use
         \:{/}
         \:{!}

      instead. This syntax is both more robust and more extensible.  This
      change is similar to previous changes introducing \`{}, \={} and \*{}.

Wed, Jul 25 2007

   *  zoem-07-205 released.

   *  Zoem is now licensed under the GNU General Public License version 3
      (or later).

   *  Added \set#3 that provides all the modalities of set#2, setx#2,
      def#2, defx#2 (namely optional warning, expansion), as well as
      additional modalities. It is possible to define a key conditionally (if
      not set already), and a key can be explicitly set in the global (bottom)
      user dictionary.

   *  \''foo will look up foo in the bottom user dictionary, allowing
      this dictionary to function as a global namespace.

   *  Success status, as written in the session macro \__zoemstat__ by try#1
      and catch#2 is now associated with the string "done" rather than "ok".
      The status "done" can now be explicitly thrown with \throw{done}{}.  In
      this case the unprocessed part of the current interpretation stack is
      discarded, but no error is generated.

      When not captured by try#1 or catch#2, \throw{done}{} can be captured by
      eval#1 and while#2.  If neither of these four primitives catches the
      throw, it is captured at the file processing level and results in
      end-of-processing for the current file. This is fully equivalent
      with what used to be the primitive \done. This primitive has now
      been implemented as the alias \throw{done}{}.

   *  The primitive \done is now implemented as \throw{done}{}.

   *  Introduced \`{..} syntax, equivalent with \`..` syntax. These are only
      available within the \formatted#1 primitive (where .. is a placeholder
      for valid formatted#1 directives).  This change is similar to previous
      changes introducing \={} and \*{}. The old \`..` syntax is deprecated
      and if it is used error messages are issued. The rationale for these
      changes is that the new syntax is more pleasant on the eye and will be
      extendible if needed.

   *  Added \ifdef#3 and \ifdef#4 aliases. This is the ifdef#3
      definition:

      \set{ifdef#3}{\if{\defined{\1}{\2}{\3}}}

   *  \defined{mode}{} now accepts modes 'zoem', 'prim', 'alias'.
      mode zoem accepts the combined classes of prim(itives) and
      alias.

   *  The command line option -s accepts 'key' as well as 'key=val'
      syntax. In the former case the value of key will be set to '1'.

   *  Added two solutions to the N-queen problem in the examples directory.

Wed, Dec 13 2006

   *  zoem-06-347 released.

   *  Fixed display bug in PUD -- the { itemize, long-item, html, safari }
      combination where long-item would be split over lines.

   *  Clean-ups and modifications in underlying util library (mostly
      hash-related).

Wed, Aug 23 2006

   *  zoem-06-234 released.

   *  Added beta key \__env__#1 to retrieve environment variable settings.
      \defined#2 tests for existence of a name in the environment with
      the ENV type.

   *  Added caveat in zoem(1) and Zoem User Manual documentation;
      \done will stop processing the current file only if it was read in its
      entirety, i.e. if the chunk size is sufficiently large. The default
      chunk size (1Mb) should be more than sufficient for authoring
      environments.

   *  The session key \__fnup__ is set to the file that includes
      the current file to aid in diagnostics.

   *  The underlying utility library was overhauled - it's integer
      type system was redone and a more rigorous design was put in place,
      following common practices (size_t and ssize_t wise).

Tue, Mar 22 2006

   *  zoem-06-080 released.

   *  A number of developments have settled with release. To sum up the most
      noteworthy items (C, F and H stem from this release):

         A) primitive namespace identification with \'
         B) user keys can shadow primitives
      +  C) user keys can inspect (vararg) argument structure with \nargs#1
  ABC => D) improved facilities for backward compatability
         E) PUD or portable UNIX documentation is now a separate entity
      +  F) \__line__ now yields what it promises
         G) many primitives recoded as user macros (counters and references)
      +  H) \switch#2 can group branches
         I) \register adds useful processing hook registration
         J) \whilst#2 flushes output immediately

   *  A long standing minor bug has been fixed. Comments up to and including
      the newline can be stripped with the sequence \:/.
      This used to corrupt the file line counter as seen in the session macro
      \__line__ and in error messages. No more.

   *  \switch#2 can collect several cases together using a vararg.
      In the \nargs#1 example below one might use e.g.

      \def{test#1}{
         \switch{\nargs{\1}}{
            {{-1}{-2}} { .. regular stuff .. }
            {   .. apply stuff .. }
         }
      }

      to do the same thing for both of the -1 and -2 cases.
      Different devices can easily be lumped together using the idiom

      \${ {{txt}{roff}}  { .. stuff A .. }
          {html}          { .. stuff B .. }
       }

       In this case the txt and roff devices pass through the same
       branch. \$#1 is a new alias introduced further below.

   *  Added \nargs#1 primitive which counts the number of scopes in its
      argument - WHICH IS NOT EVALUATED. This allows construction of user
      macros that can overload one or more particular arguments, i.e.  behave
      differently depending on the number of scopes in the argument.

      A likely application is an argument that either specifies a simple
      string (assuming default modes) or a vararg with strings and 
      modes specified using a key-value vararg.
      One usage is to extend a macro's functionality while retaining
      backward compatibility.

      \nargs{{abc}def}     : -2      \: neither fish nor fowl
      \nargs{abc}          : -1      \: regular argument
      \nargs{abc{def}}     : -1      \: regular argument too
      \nargs{}             :  0      \: empty vararg (not empty regular arg)
      \nargs{   }          :  0      \: empty vararg again
      \nargs{{abc}}        :  1      \: vararg with 1 argument
      \nargs{{abc}{def}}   :  2      \: vararg with 2 arguments
      \nargs{   {abc}
                {def}
      }                    :  2      \: vararg with 2 arguments
      etc.

      User macros can now use a framework such as

      \def{test#1}{
         \switch{\nargs{\1}}{
            {-2}{\inform{mixed feelings}\exit}
            {-1}{ .. regular stuff .. }
            {  \switch{\let{\nargs{\1}%2}}{
                  {0}{\apply{_#2\!{{ .. stuff with \1 and \2 .. }}}{\1}}
                  {\inform{vararg invocation requires paired arguments\exit}}
               }
            }
         }
      }

      to branch on scope presence/absence. The purpose of the -2 return value
      is to promote frameworks that spot errors early. Group -2 and -1
      as {{-2}{-1}} within switch to make them pass through the same branch.

   *  Added $#1 and $#3 aliases.
      $#1 maps to \switch{\__device__}{\1}            \: switch
      $#3 maps to \switch{\__device__}{{\1}{\2}{\3}}   \: ifelse

   *  within write#3 invocations the key \__fnwrite__ is set to the
      appropriate output file name. This allows easy branching on the file
      being written to from macros accessed within the third argument. The key
      is deleted after evaluation of the third argument has finished.  Nested
      invocations will currently overwrite this key.

   *  Spreading \foo over two lines as in
      \fo\:/
      o

      (with the 'o' at the beginning of line) will be correctly parsed
      regardless of chunk size.

Wed, 22 Feb 2006

   *  zoem-06-053 released.

   *  inspect#4 was broken since the previous release; the parse
      code responsible for firing of the callback macro had not
      been updated properly. Fixed.

   *  minor documentation improvements.

   *  The TODO was shrunk to a more reasonable size and PUD
      now has its own DOPUD.

Wed, 15 Feb 2006

   *  zoem-06-046 released.

   *  Major clean-ups in both code and documentation. Facilitated
      syntactic separation of primitives and user macros.

   *  (minor) Backward incompatible change in the PUD macro package.

      As a further clean-up of the reference framework (in which refload#2
      and friends moved to ref.zmm), publanch#2 and publref#1 have now
      moved to ref.zmm and have been renamed to reference#2 and refer#1
      for better consistency.

      ref.zmm is now documented in pud-ref(7).

   *  pud-ref(7)
      pud(7)

      were added. The first describes the reference framework, which was
      recently removed from the Zoem User Manual as it is no longer
      implemented by primitives. The second is an introduction to and an
      overview of Portable Unix Documentation.

   *  The counter primitives \ctradd#2, \ctrset#2, \ctrput#1 and the builtins
      \ctrinc#2 and \ctrdec#2 were recoded as user macros in the new macro
      package ctr.zmm .

   *  For primitives or builtins with standard alphabetic names
      and the special primitive \$#2 and the special builtins
      \"" and \""#1 the syntax

         \'standard{arg1}..
         \'${arg1}{arg2}
         \'""
         \'""{arg1}

      is now accepted. Moreover, primitive definitions can be shadowed in
      the user dictionary. Currently a warning is issued when this happens.

      The prefered way of accessing primitives is now with the new syntax.
      This makes existing zoem files compatible in case future zoem
      primitives clash with user-defined keys.

      It also makes works based on such files still extendible since the
      new primitive can be unambiguously accessed by the new syntax.

      Finally, with the new syntax zoem needs to do less hash table
      lookups, making it again slightly faster. Said tiny speed increment
      has been fully negated by the redefinition of counter primitives
      as user macros however.

   *  The number of builtin aliases has been cut back.

   *  The idiosyncratic \> (close XML-type tag) syntax has been removed.
      Use \<> or explicit \ style syntax.

   *  Cleanups and deduplication in the parsing code. Examples:
         \apply{<>#2}{{foo}{bar}}
         \apply{$#2}{{html}{yes}}
      now do something. You probably will not need it.
         \def{<>}{foo}
      now chokes.

   *  Documentation fixes and additions.

Tue, 10 Jan 2005

   *  zoem-06-010 released.

   *  Assembled the man and FAQ macros under the Portable Unix
      Documentation label.

      -  the man_zmm(7) manual page was renamed to pud-man.
      -  the faq_zmm(7) manual page was renamed to pud-faq.
      -  the generic_zmm(7) manual page was renamed to pud-base.

   *  Redid a lot of documentation. Further separated package descriptions
      from core zoem documentation.

Thu 5 Jan 2006

   *  zoem-06-005 released.

   *  Pruned the Zoem User Manual to only describe the core zoem language.
      Diatribes and mini-language excursions were removed.

   *  A missing clearerr in util/io.c caused
         ./zoem --unsafe -E '\register{END}{\system{date}}'
      to loop on EOF on at least one architecture (mac OSX). Fixed.

Thu, 24 Nov 2005

   *  zoem-05-328 released.

   *  This release contains substantial behind-the-scenes changes.
      Oddbal zoem primitives were reimplemented as macros of exisisting
      primitives or as special cases of a new more generic primitive.  Users of
      packages (man, faq, doc) should not be affected, with this exception:
       ____________________________________________________________________ 
      {                                                                    }
      {  The new zoem will choke on existing *.zmr and *.zmt auxiliary     }
      {  files. Remove these and you should be fine.                       }
      {____________________________________________________________________}

      The reason being that the primitive refload#6 is now replaced by
      the macro refload#2 provided by the new ref.zmm package.

   *  Added \register#2, use e.g. as

      \register{END}{
         \if{\ctrput{zoem::ref::misses}}{
          \write{stderr}{txt}{>>> [REF] \ctrput{zoem::ref::misses} missing references\|}
         }{}
      }

      This example is from the file ref.zmm that now implements zoem
      references.  This particular registered macro outputs a warning after all
      input has been processed if missing references were found during a run.

      Currently only END is supported. registered macros are processed in
      the order of registration.

   *  Reference handling was removed from the core zoem language.
      \refload#6 and \ref#2 were reimplemented as simple macros (\refload#2 and
      \ref#2) using the zoem data facilities and the new register#2 primitive.
      They are found in the new macro file ref.zmm.

      \refloadx#2 was added, it can be used to attach custom information to
      a reference.

   *  \ucase#1 \roman#1 and \alpha#1 are reimplemented as simple
      macros - and deprecated. They are now specific invocations
      of the new \textmap#2 primitive.

   *  \textmap#2 implements a variety of text transformations. Among them:

         {word}{ucase}
         {word}{lcase}
         {number}{roman}
         {number}{alpha}
         {caesar}{}
         {vigenere}{}
         {vigenerex}{}

      These transformations are applied sequentially, implying that

         \textmap{{number}{roman}{word}{ucase}}{\your_nice_counter}

      does what you expect it to do. Use caesar and vigerene[x] to
      encrypt your sensitive data.

   *  Added \whilst2, which sends output to the current output file
      without building up intermediate results.

   *  The tr#4 was sanitized. See further below.

   *  The zoem output implementation was thoroughly cleansed
      and is in a maintainable state now. This bears on the handling of
      multiple output sinks (altiplexing?).

      Same for environment well-formedness checks.  As part of the clean-up an
      experimental (but backwards compatible) feature was put in place; see
      immediately below.

   *  This item is important only for people that write their own
      environment definitions.  Dictionary stacks are now tied to (output)
      sinks. This implies that

      \begin{foo}
         \write{zutfut}{device}{\begin{zut}}
      \end{foo}
         \write{zutfut}{device}{\end{zut}}

      is now legal zoem, and any dollar key within a write scope is tied to the
      output stream defined by the write invocation.  Different instances of
      the same environment spread over different output sinks will thus not
      clobber one another.

      If a dollar key is not found within some write scope, it is searched
      in the default output scope.

   *  added \genoptref#1 to the generic package, for generic (html) linking to
      an option only using the option identifier string.

   *  The first argument of inspect now takes a vararg rather than
      a single string. The modifiers previously accepted as the first
      argument are now accepted as argument to the 'mods' key.
      So use e.g. \inspect{{mods}{count-matches}}{..}{..}{..}
      if counting matches is what you are after.

   *  Incompatible change in what presumably is one of the
      lesser-used primitives.

      Removed \tr#4 because its interface was broken beyond repair.
      Added \tr#2.

         \tr{  {from}{from-spec}
               {to}{to-spec}
               {delete}{delete-spec}
               {squash}{squash-spec}
            }{
               data
            }

      Data is unprotected, all specs are subject to tilde expansion.

      Specs are largely POSIX compliant except that repeats are
      denoted

         [*c*20]     \: repeat c 20 times
         [*\012*20]  \: repeat newline 20 times
         [*X*]       \: fill with X
         [*X#]       \: repeat X until class/range boundary

      The magic repeat operator # stops on boundaries. A boundary happens at
      start or end of a class or range.  Complements are denoted by a leading
      caret.

   *  \push#1 and \pop#1 semantics have changed.  \push#1 now always pushes the
      user dictionary stack. Its argument now denotes the name of dictionary
      stack that is pushed.  The matching \pop#1 should specify the same name.

   *  made -o work with -e and -E.

   *  rewrote parts of zmm_generic for the html device. It now makes
      more use of style sheets and is reworked towards better
      customizability.

   *  Included a description of the \inspect#4 and \format#2
      (mini-mini) sublanguages in the zoem(1) manual. This covers
      respectively tilde expansion for \inspect#4 and the format
      specification strings for \format#2.

   *  itemize accepts {smallertext}{1}

   *  Added fase support for centering with \format#2. With centering,
      the default now is that strings of length 1 and 2 will be layed-out
      thusly:           (even width)
         [....8...]
         [....9...]
         [...10...]
         [...11...]
      or                (odd width)
         [....8....]
         [....9....]
         [...10....]
         [...11....]
      This can be changed by using '==' as the centering specification:
         [...8....]
         [...9....]
         [...10...]
         [...11...]
      and
         [....8....]
         [....9....]
         [....10...]
         [....11...]

      This pattern applies generally to strings of length (2*k+1, 2*k+2).
      In case you need it, the fase will alternate with each equal sign
      appended to it.

   *  Zoem's \alpha#1 macro (now implemented as
      \textmap{{number}{roman}}{\1}) transforms numbers to strings by writing
      them in base 27, using _ as zero.  It's use is primarily to enable a) b)
      c) style itemization.  While experimenting with alpha#1, I found that

         \alpha{1444} = azm

     The most wonderful coincidence as azm is the zoem suffix
     and 1444 is 38 squared - 38 is one of my lucky numbers no less.

     This is a universal truth rather than a change. However, the simple act of
     perceiving a universal truth instantly creates truth ripples through the
     fabric of everything, and in doing so changes the course of the universe
     in profound ways.  I thought you might like to know this.

Fri, 3 Jun 2005

   *  zoem-05-154 released.

   *  Fixed segmentation fault occurring with -e option, introduced
      in previous release.

   *  Added a regression test suite, stress2.azm.
      stress.azm is now also called a regression test suite.

   *  Tested a large number of error paths, fixed a few
      to yield truncated output as they should.

   *  Fixed doc.zmm to produce better W3C compliant output -
      specifically compliant  anchors.

   *  Added a tilde escape mechanism to inspect#4 to prevent
      cumbersome regexes when slashes are needed (either as a
      literal or as a regex metacharacter).

   *  Sanitized the \inspect#4 implementation and interface.
         supported options:
            iter-args            (was vararg)
            iter-lines           (was lines)
            discard-nmp          (was skip)  [non-matching-part]
            discard-nil-out      (was snip)
            count-matches        (was count)
            discard-miss
            dotall
            icase

Tue, 24 May 2005

   *  zoem-05-144 released

   *  Writeto obeys the --unsafe and --unsafe-silent options (or their
      absence) when its filename contains a path separator, the forward
      slash (entirely UNIX-centric). Such a path separator is considered
      a risk in overwriting sensitive files. Zoem will prompt
      the user according to the safety settings. It will never prompt the
      user if the filename does not contain a path separator.

   *  The primitive env#3 has become env#4 and env#3 is now a macro
      expanding to \env{\1}{}{\2}{\3}.
      The second argument of env#4 is a list of key-value pairs
      in a vararg that are set as default dollar keys. This simplifies
      the definition of environments.

   *  keys set in the second (vararg) argument begin#2 can now
      be keys taking arguments. e.g.

         \begin{foo}{{bar#2}{\!2\!1}}

      defines a key that is used as

         \$bar{a}{b}

      which would result in

         ba

   *  Environments set \$__args__ and \$__xargs__ so that they can pass
      the full argument list onwards if needed.

   *  Environments will now silently overwrite local keys previously defined.
      This enables a convenient override system when one environment
      encapsulates another environment - it can append user arguments
      (using \$__args__) to default settings.

   *  Changed --allow=[:]* syntax to
      -allow [:]* syntax.

   *  Moved option parsing to structured mcxOption framework.

Mon, 21 Jun 2004

   *  zoem-04-173 released.

   *  Repeated use of \special#1 would decrease available stack space.
      Quite rare bug revealed by Tim Hughes as one of the first to use
      clmformat/zoem on a larger scale.
      This will not affect normal usage of zoem.
      Fixed.

   *  Made the code better ISO-C compliant (split long constant strings).

Wed, 16 Jun 2004

   *  zoem-04-168 released.

   *  fixed embarassing special-related bug. It *did* affect exisiting macro
      packages (see below).

Tue, 15 Jun 2004

   *  zoem-04-167 released.

   *  \special#1 now evaluates its argument. This does not affect existing
      macro packages.

   *  Updated generic_zmm documentation.

   *  Treat spaces in manual name correctly (fixed bug in man.zmm results
      spotted by Joost van Baal).

Sun, 13 Jun 2004

   *  zoem-04-165 released.

   *  fixed bug where inline files would cause zoem to crash.

   *  introduced enclosing variants for all paragraph incarnations.
      \par     ->    \par#1         (content)
      \cpar#1  ->    \cpar#2        (caption, content)
      \car     ->    \car#1         (content)
      \ccar#1  ->    \ccar#2        (caption, content)
      Separation tags (such as \par) will be phased out from the
      zoem macro packages. \item and \sec are to follow.

   *  \formatted#1 now skips \<> scope as well.

   *  Embedded newlines in *ml syntactic sugar \<..> would screw up the
      line count. Now fixed.

   *  \<> stacks are now tied to files, so that alternating output
      can never erroneously corrupt the well-formedness stack. (Do note that
      funny user-side inverse processing could and still can do that).

   *  Environment stacks (\begin and \end stuff) are now also tied to files,
      same as above.

   *  The hash module in the underlying library code was overhauled.
      hashes now maintain private storage for links and key-value pointers.

Tue, 20 Apr 2004

   *  zoem-04-111 released.

   *  small documentation fixes.


Mon, 19 Apr 2004

   *  zoem-04-110 released.

   *  the builtin alias \error#1 is gone, replaced by \inform#1.

   *  Streamlined the examples, made them more suitable for web-publishing.

   *  Fixed a bug recently introduced into the util library;
      file read from STDIN would only read a single line.

   *  (updated web index, otherwise irrelevant).

Sat, 17 Apr 2004

   *  zoem-04-108 released.

   *  Some activity at meta-zoem primitive level.
      A new exception mechanism was fully integrated with the error
      framework.

      -  Introduced \throw#2, which generalizes \quit (now removed).
      -  Removed \zoem#1. It is generalized by \catch{label}{expression}
         and \try{expression}.
      -  Reimplemented \quit as \done, specialized for clean premature
         file exit.

      This enables

         \catch{towel}{
            \while{1}{
               do stuff
               \if{ifstuff}{\throw{towel}}{}
               do stuff
            }
         }

      and
      
         \catch{error}{
            do possibly erroneous *or* towel stuff
         }

      or

         \try{ stuff }

         inspect
            \__zoemstat__ (towel|error|ok) and
            \__zoemput__  (the possibly truncated result of \try{stuff})

      \catch#2 and \try#2 can be arbitrarily nested.
         
   *  The primitive \throw#2 is used as
         \throw{towel}{msg}
         \throw{error}{msg}

      The macros
         \throw{towel}
         \throw{error}

      expand to \throw{towel}{} and \throw{error}{} and do not issue a message.

   *  The new alias \error#1 generates an error message, it expands to
      to \write{stderr}{device}{\1\@{\N}}

   *  Removed alias \ignore#1, use \""#1 instead.
      (e.g. \""{ignore
               stuff
            }
      )

   *  Fixed zum.azm, which contained bogus begin#1 description.

   *  Fixed small bug; \write#3 would erroneously set \__fnout__.
      Using \__fnout__ as in \write{\__fnout__}{filter}{stuff}
      now works as expected.

Wed, 7 Apr 2004

   *  zoem-04-098 released.

   *  fixed documentation to exclusively use/describe the begin#2 primitive.

   *  The old and ugly \begin{itemize{{foo}{bar}}} syntax now generates
      a syntax error. (use \begin{itemize}{{foo}{bar}}, introduced
      in zoem-04-072).

   *  fixed -e option related bug, changed its implementation.

   *  Introduced \*{'e} syntax, equivalent with \*'e* syntax. The new syntax
      is optionally extendible and more in line with the rest of zoem.
      This move is similar to the inline file name change \=fname= -> \={fname}
      introduced earlier.  The old \*'e* syntax will not be removed but
      if used error messages are issued.

   *  The \formatted#1 tokens \`<` and \`>` were changed to \`[` and \`]` for
      esthetic reasons.

Tue, 30 Mar 2004

   *  zoem-04-090 released.

   *  Fixed some small documentation glitches.

   *  At request of the zoem user community, the faqsec environment
      was moved to a key/value based syntax. The two positional arguments
      
___ [zoem] unwound on error/exception store
line number. zoem-11-166/depcomp0000755000402500021140000003554511063270741011065 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2004-05-31.23 # Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. # This program 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 2, 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 General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit 0 ;; -v | --v*) echo "depcomp $scriptversion" exit 0 ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test -f "$tmpdepfile"; then : else stripped=`echo "$stripped" | sed 's,^.*/,,'` tmpdepfile="$stripped.u" fi if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then outname="$stripped.o" # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # Dependencies are output in .lo.d with libtool 1.4. # With libtool 1.5 they are output both in $dir.libs/$base.o.d # and in $dir.libs/$base.o.d and $dir$base.o.d. We process the # latter, because the former will be cleaned when $dir.libs is # erased. tmpdepfile1="$dir.libs/$base.lo.d" tmpdepfile2="$dir$base.o.d" tmpdepfile3="$dir.libs/$base.d" "$@" -Wc,-MD else tmpdepfile1="$dir$base.o.d" tmpdepfile2="$dir$base.d" tmpdepfile3="$dir$base.d" "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi if test -f "$tmpdepfile1"; then tmpdepfile="$tmpdepfile1" elif test -f "$tmpdepfile2"; then tmpdepfile="$tmpdepfile2" else tmpdepfile="$tmpdepfile3" fi if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: zoem-11-166/install-sh0000755000402500021140000001273607465775502011531 00000000000000#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 zoem-11-166/missing0000755000402500021140000002466611063270741011111 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2003-09-02.23 # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 # Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program 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 2, 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 General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA # 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Send bug reports to ." ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal*) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then # We have makeinfo, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; tar) shift if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 fi # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: zoem-11-166/configure.ac.in0000644000402500021140000000552411576203251012376 00000000000000# $Id: configure.ac.in,v 1.15 2004/06/09 16:42:58 flux Exp $ ## are we using AC_CONFIG_HEADERS? ## in http://www.gnu.org/software/autoconf/manual/autoconf.html#Writing-Autoconf-Input ## it is suggested that this is required to output config.h ## we are using AM_CONFIG_HEADER instead. How does this work? # Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) AC_INIT(zoem, setversion_VERSION, stijn@micans.org) PACKAGE=$PACKAGE_NAME VERSION=$PACKAGE_VERSION AC_CONFIG_SRCDIR([src/segment.c]) AM_INIT_AUTOMAKE($PACKAGE, $VERSION) AC_CONFIG_HEADERS(config.h) # AC_CONFIG_HEADERS([config.h]) # add a `--enable-maintainer-mode' option to `configure'; `maintainer-only' rules turned off by # default in Makefile.in's AM_MAINTAINER_MODE AC_SUBST(PACKAGE) AC_SUBST(VERSION) AC_ARG_WITH( includepath, AC_HELP_STRING( [ --with-includepath=DIR ], [ a colon separated list of directories where to look for definition files. It is overridden by the environment variable ZOEMSEARCHPATH, if set. The default is PREFIX/share/aephea. If Aephea files are installed e.g. as /opt/aephea/aephea/simpledocument.zmm /opt/aephea/pud/man.zmm then pass --with-includepath=/opt/aephea. If aephea is installed with the same PREFIX as zoem, nothing need be done. ] ), [ if test "x$prefix" != xNONE; then ac_cv_use_includepath=$withval:$prefix/share/aephea else ac_cv_use_includepath=$withval:/usr/local/share/aephea fi ], [ if test "x$prefix" != xNONE; then ac_cv_use_includepath=$prefix/share/aephea else ac_cv_use_includepath=/usr/local/share/aephea fi ] ) AC_CACHE_CHECK( Include path(s) to add, ac_cv_use_includepath, [ if test "x$prefix" != xNONE; then ac_cv_use_includepath=$prefix/share/aephea else ac_cv_use_includepath=/usr/local/share/aephea fi ] ) AC_DEFINE_UNQUOTED(INCLUDEPATH, $ac_cv_use_includepath, [ where to look for zoem macro files ]) AC_SUBST(ac_cv_use_includepath) # Checks for programs. AC_PROG_AWK AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_RANLIB # Checks for libraries. # Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS([fcntl.h float.h limits.h stdlib.h string.h ]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_PID_T # Checks for library functions. AC_FUNC_VPRINTF AC_FUNC_FORK AC_FUNC_MALLOC AC_FUNC_MEMCMP # AC_FUNC_REALLOC AC_MMX_OPTION_READLINE AC_CHECK_FUNCS([dup2 floor memset pow regcomp sqrt strchr strrchr strstr]) AC_CHECK_VA_COPY # AC_CONFIG_FILES([]) AC_OUTPUT([ Makefile doc/Makefile examples/Makefile src/Makefile util/Makefile ]) zoem-11-166/bootstrap0000755000402500021140000000155407705461076011457 00000000000000#!/bin/sh -e # $Id: bootstrap,v 1.9 2003/07/17 08:45:50 flux Exp $ # # bootstrap - script to bootstrap the distribution rolling engine # # to build a tarball, ready for distribution, from fresh checked out # cvs sources, do # # automake --add-missing && ./bootstrap && ./configure && make distcheck # # this will yield a tarball, e.g. zoem-20020109.tar.gz . Once this has been # run, one can, after e.g. editing sources, run just # # make distcheck # # to generate a new tarball. (No need to run ./bootstrap again in this case.) # After downloading, users do # # tar zxf mcl-20020109.tar.gz # cd mcl-20020109 # ./configure && make # make install # set -x if test ! -f VERSION then ./setversion fi if test ! -L util/Makefile.am then ./mkutil fi aclocal \ && autoheader \ && automake --verbose --gnu --add-missing \ && autoconf zoem-11-166/setversion0000755000402500021140000000146011446400667011633 00000000000000#!/bin/sh -e # $Id: setversion,v 1.14 2006-03-21 11:10:01 flux Exp $ # called in bootstrap # alias date='date -d "2007-11-29"' # be verbose set -x VERSION=`date '+%y-%j'` echo $VERSION > VERSION cat > configure.ac <> configure.ac vsh='src/version.h' echo -n '' > $vsh echo '#ifndef zoem_version_h__' >> $vsh echo '#define zoem_version_h__' >> $vsh echo 'char *zoemDateTag;' >> $vsh echo '#endif' >> $vsh vsc='src/version.c' echo -n '' > $vsc echo 'char *zoemDateTag = "'`date +%Y-%j`'";' >> $vsc date '+%y-%j' > doc/stamp.stamp date '+%e' > doc/stamp.day date '+%b' > doc/stamp.month date '+%Y' > doc/stamp.year zoem-11-166/VERSION0000644000402500021140000000000711576203373010547 0000000000000011-166 zoem-11-166/LICENSE0000644000402500021140000000240210651620176010502 00000000000000 This directory contains source code implementing an interpreter for the Zoem language, and extensive documentation and examples covering the zoem interpreter, the zoem language, and two macro packages written in the zoem language. All C source and header files (with '.c' and '.h' extensions) and all zoem source files (with '.azm' and '.zmm' extensions) in the subdirectories of this directory are copyright (c) 2001-2007 Stijn van Dongen, stijn micans org, as are the documentation files derived from the zoem source files. This program 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. 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. zoem-11-166/TODO_DESIGN0000644000402500021140000000655711321607151011226 00000000000000 An attempt at distilling some mainlines from TODO. - better structuring and sectioning of source code. parse/segment/digest include most of each other, due e.g. to seg_check_ok and yamFormatted1. - Env well-formedness should pbb best be checked at output time, not during processing time. It should be possible (?) to make contrived examples failing during processing time, producing correct output nevertheless. - A design for allowing overwriting primitives? A design for setting keys in the bottom dictionary (defg, defgx, setg, setgx) An extenstion design where zoem primitives are lexically recognizable. Hum. g global x expand c conditional (only if not defined) - implement append modes \writeto{a}{name}, \write{a}{name}{filter}{stuff}. For writeto also make commandline switch that makes \writeto{name} append by default. - better hashing of file pointers (right now by name, so foo and ./foo are different). - remove 9-arg limitation. - better special/level design. - the implementation of f#2 f#3 and fv#2 is very straightforward from a numerical point of view. - (ever) better separate character munging code. clearer grip on device whitespace munging and special rules for the extreme corner cases. - fix long routines. - reconsider tracing implementation. - who gets to err and why (given all the unwinding)? further qualify stacks + dictionaries with associated sink? or, perhaps, \get{itemize}{foo} will search across all stacks irrespective of sink. zum.azm: boot wt new 1 0 1 0 0 1 0 0 0 0 0 1 zoem.azm boot wt new 1 0 1 0 0 1 0 1 1 [][][][]| | |____| ^ ^ [][][][]| | ----------------- ..... |____| ^ [][][][]| | ^ |____| [][][][]| | ----------------- ..... ^ |____| ^ ^ sink_default ^ writeto busystack push pop getDLRtop dollarstack tied to output. default dollarstack: changed by writeto. aephea: \writeto{-} \begin{presentation} \writeto{1.html} \begin{slide} \get{$presentation}{foo} \write{index.htmL}{device}{.... ??\get{$presentation}{foo}?? ...} \end{slide} write3 yamOutputNew(fname->str)) yamKeyDef("__fnwrite__", fname->str) yamOutput(yamtxt, xfout->usr, fltidx) sinkPush(sk, fltidx) sinkPop(sk) writeto yamOutputClose yamOutputNew if (!xf->usr) xf->usr = sinkNew else filterSetFP sinkPush ## changed sinkPush: does this fix it? write - in zpresent \writeto{} makes env {presentation} inaccessible. 1) is there a global dollar stack? (yes, sinkGetDLRdefault) 2) why is env presentation not tied to it? a) is there a way to tie it? b) if no, make it. -> way to specify that dictionary should be tied to DLRdefault. -> OR \writeto should act the same as \write -> and optionally make that configurable. zoem-11-166/DESIGN0000644000402500021140000000404110040305570010360 00000000000000 Varargs Scopes may be separated by whitespace; any other character is treated as end-of-vararg. For some unknown reason, the occurrence of such hickup-characters is not yet treated as an error. XML syntactic sugar \{stuff} is *different*, because of immediate digest and delay until output time. In fact, \{\!{\PI}} will work because of extra digest in evalXtag2. I am not yet aware of an example where the inserted delay scope throws a surprise. Segment continuation, so to speak In case of error, ops should always use yamSegPush(seg, txt) so that partial content is treated correctly. Use mcxTingEmpty if necessary, or just pass partial content, or use yamSegPushEmpty(seg) yamSegPush(NULL, ..) should only be issued by yamStackPush in segment.c, nowhere else. This is not yet enforced/checked; stuff needs to be reglued a bit for this. yamSegPush never returns NULL, but may set SEGMENT_ERROR or SEGMENT_THROWN, which should be checked. yamExpandKey and yamDoKey may return NULL, these must be checked. yamStackPush / yamStackFree are not symmetric. the freeing is usualy done from a higher level (in case of error) or implicitly by totally rewinding and using yamSegFree. yamStackPushTmp / yamStackFreeTmp *must* be symmetric. This is not yet checked (e.g. one might erroneously use yamSegFree to free the stack obtained by yamStackPushTmp). One way would be to set a special flag that is checked e.g. by yamSegNew, but alas apply2 issues yamSegNew after yamStackPushTmp. yamDigest returns 2 statuses, FAIL and OK. yamOutput returns 3 statuses, BOUNCE, FAIL, and OK. (yamDigest writes info in baseseg [what happens when baseseg == NULL?]) this is either not entirely satisfactory or needs to have clear exposition. Tracing Tracing should mainly serve the zoem user, not the developer. So don't put too many debugging-type tracing levels in. Allocation errors memalloc errors are not caught. Zoem should be compiled to exit on error. zoem-11-166/util/0000777000402500021140000000000011576212301010532 500000000000000zoem-11-166/util/Makefile.am0000644000402500021140000000137311030660341012502 00000000000000## Process this file with automake to produce Makefile.in ## $Id: Makefile.am-assimilate,v 1.3 2005-12-07 16:58:40 flux Exp $ INCLUDES = -I$(top_srcdir) noinst_LIBRARIES = libutil.a libutil_a_SOURCES = alloc.c array.c rand.c equate.c opt.c io.c \ err.c hash.c heap.c let.c list.c gralloc.c tok.c ting.c ding.c \ tr.c types.c EXTRA_DIST = alloc.h array.h rand.h equate.h hash.h heap.h let.h io.h \ opt.h err.h tok.h ting.h ding.h list.h gralloc.h tok.h \ compile.h getpagesize.h types.h inttypes.h minmax.h tr.h zoem-11-166/util/Makefile.in0000644000402500021140000003362011576203400012517 00000000000000# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ 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 = : subdir = util DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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 = CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) AR = ar ARFLAGS = cru libutil_a_AR = $(AR) $(ARFLAGS) libutil_a_LIBADD = am_libutil_a_OBJECTS = alloc.$(OBJEXT) array.$(OBJEXT) rand.$(OBJEXT) \ equate.$(OBJEXT) opt.$(OBJEXT) io.$(OBJEXT) err.$(OBJEXT) \ hash.$(OBJEXT) heap.$(OBJEXT) let.$(OBJEXT) list.$(OBJEXT) \ gralloc.$(OBJEXT) tok.$(OBJEXT) ting.$(OBJEXT) ding.$(OBJEXT) \ tr.$(OBJEXT) types.$(OBJEXT) libutil_a_OBJECTS = $(am_libutil_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libutil_a_SOURCES) DIST_SOURCES = $(libutil_a_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_cv_use_includepath = @ac_cv_use_includepath@ 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_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = -I$(top_srcdir) noinst_LIBRARIES = libutil.a libutil_a_SOURCES = alloc.c array.c rand.c equate.c opt.c io.c \ err.c hash.c heap.c let.c list.c gralloc.c tok.c ting.c ding.c \ tr.c types.c EXTRA_DIST = alloc.h array.h rand.h equate.h hash.h heap.h let.h io.h \ opt.h err.h tok.h ting.h ding.h list.h gralloc.h tok.h \ compile.h getpagesize.h types.h inttypes.h minmax.h tr.h all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 util/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu util/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libutil.a: $(libutil_a_OBJECTS) $(libutil_a_DEPENDENCIES) -rm -f libutil.a $(libutil_a_AR) libutil.a $(libutil_a_OBJECTS) $(libutil_a_LIBADD) $(RANLIB) libutil.a mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/array.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ding.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/equate.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/err.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gralloc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/let.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ting.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tok.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/types.Po@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) '$<'` 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: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ 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: $(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" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 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 check: check-am all-am: Makefile $(LIBRARIES) 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags 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 -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-generic distclean-tags 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-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am # 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: zoem-11-166/util/alloc.c0000644000402500021140000000757711147245774011742 00000000000000/* (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ /* include include include include */ #include #include #include #include "alloc.h" #include "err.h" static dim mcx_alloc_maxchunksize = 1048576; static long mcx_alloc_maxtimes = -1; static mcxbool mcx_alloc_limit = FALSE; void mcxAllocLimits ( long maxchunksize , long maxtimes ) { if (maxchunksize > 0) mcx_alloc_maxchunksize = maxchunksize ; if (maxtimes > 0) mcx_alloc_maxtimes = maxtimes ; mcx_alloc_limit = TRUE; ; } void* mcxRealloc ( void* object , dim new_size , mcxOnFail ON_FAIL ) { void* mblock = NULL ; mcxstatus status = STATUS_OK ; const char* me = "mcxRealloc" ; if (!new_size) { if (object) mcxFree(object) ; } else { if ( mcx_alloc_limit && (!mcx_alloc_maxtimes-- || new_size > mcx_alloc_maxchunksize) ) mblock = NULL ; else mblock = object ? realloc(object, new_size) : malloc(new_size) ; } if (new_size && (!mblock)) mcxMemDenied(stderr, me, "byte", new_size) , status = 1 ; if (status) { const char* tin = getenv("TINGEA_MEM_SIGNAL") ; if (tin) { unsigned tintin = atoi(tin) ; raise(tintin ? tintin : SIGSEGV) ; } if (ON_FAIL == SLEEP_ON_FAIL) { mcxTell(me, "pid %ld, entering sleep mode", (long) getpid()) ; while(1) sleep(1000) ; } if (ON_FAIL == EXIT_ON_FAIL || ON_FAIL == ENQUIRE_ON_FAIL) { mcxTell(me, "going down") ; if (ON_FAIL == ENQUIRE_ON_FAIL) mcxTell(me, "ENQUIRE fail mode ignored") ; exit(1) ; } } return mblock ; } void mcxNFree ( void* base , dim n_elem , dim elem_size , void (*obRelease) (void *) ) { if (n_elem && obRelease) { char *ob = base ; while (n_elem-- > 0) obRelease(ob) , ob += elem_size ; } mcxFree(base) ; } void* mcxNAlloc ( dim n_elem , dim elem_size , void* (*obInit) (void *) , mcxOnFail ON_FAIL ) { return mcxNRealloc(NULL, n_elem, 0, elem_size, obInit, ON_FAIL) ; } void* mcxNRealloc ( void* mem , dim n_elem , dim n_elem_prev , dim elem_size , void* (*obInit) (void *) , mcxOnFail ON_FAIL ) { char* ob ; mem = mcxRealloc(mem, n_elem * elem_size, ON_FAIL) ; if (!mem) return NULL ; if (obInit && n_elem > n_elem_prev) { ob = ((char*) mem) + (elem_size * n_elem_prev) ; while (n_elem-- > n_elem_prev) /* careful with unsignedness */ { obInit(ob) ; ob += elem_size ; } } return mem ; } void mcxMemDenied ( FILE* channel , const char* requestee , const char* unittype , dim n ) { mcxErrf ( channel , requestee , "memory shortage: could not alloc [%lu] instances of [%s]" , (ulong) n , unittype ) ; } void mcxFree ( void* object ) { if (object) free(object) ; } void* mcxAlloc ( dim size , mcxOnFail ON_FAIL ) { return mcxRealloc(NULL, size, ON_FAIL) ; } zoem-11-166/util/array.c0000644000402500021140000003033211556253460011742 00000000000000/* (C) Copyright 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #include #include #include #include #include "array.h" #include "alloc.h" #include "types.h" #include "err.h" #include "minmax.h" mcxstatus mcxSplice ( void* base1pptr , const void* base2ptr , dim size /* size of base1 and base2 members */ , dim *pn_base1 /* # base1 elements currently in use */ , dim *pN_base1 /* # base1 elements for which is malloced */ , ofs O_base1 /* splice relative to this element */ , dim d_base1 /* delete this number of elements */ , dim c_base2 /* number of elements to copy */ ) { char **ppr1 = (char **) base1pptr ; char* dummy ; const char *ptr2 = (const char *) base2ptr ; dim n_base1 = *pn_base1 ; dim N_base1 = *pN_base1 ; dim m_base1 = 0, o_base1 = 0 ; const char *errMsg = "" ; mcxstatus stat = STATUS_FAIL ; do { if (n_base1 > N_base1) { errMsg = "integer arguments not consistent" ; break ; } if (n_base1 + c_base2 < d_base1) { errMsg = "overly deleterious" ; break ; } m_base1 = (n_base1 + c_base2) - d_base1 /* new size */ ; if (O_base1 >= 0) o_base1 = O_base1 ; else { if ((dim) -O_base1 > n_base1 + 1) { errMsg = "offset specification out of bounds" ; break ; } o_base1 = (n_base1 + 1) + O_base1 ; } if (o_base1 > n_base1) { errMsg = "computed splice offset not in bounds" ; break ; } if (*ppr1 == NULL && ptr2 == NULL) { errMsg = "source and destination both void" ; break ; } if (o_base1 + d_base1 > n_base1) { errMsg = "not that many elements to delete" ; break ; } stat = STATUS_OK ; } while (0) ; if (stat != STATUS_OK) { mcxErr("[mcxSplice PBD]", "%s", errMsg) ; mcxErr ( "[mcxSplice PBD]" , "[n1, %lu] [N1, %lu] [o1, %lu] [d1, %lu] [c2, %lu]" , (ulong) n_base1, (ulong) N_base1 , (ulong) O_base1 , (ulong) d_base1, (ulong) c_base2 ) ; return STATUS_FAIL ; } if (m_base1 > N_base1) { if (!(dummy = mcxRealloc(*ppr1, size*m_base1, RETURN_ON_FAIL))) { mcxMemDenied(stderr, "mcxSplice", "void", m_base1) ; return STATUS_FAIL ; } *pN_base1 = N_base1 = m_base1 ; *ppr1 = dummy ; } if (o_base1 < n_base1) memmove ( *ppr1 + size*(o_base1 + c_base2) , *ppr1 + size*(o_base1 + d_base1) , size*(n_base1 - o_base1 - d_base1) ) ; if (c_base2) memcpy ( *ppr1 + size * (o_base1) , ptr2 , size*(c_base2) ) ; *pn_base1 = m_base1 ; return STATUS_OK ; } /* fixme, this implementation looks ugly (nested while). use instead: ; for (offset=1;offsetmempptr = mempptr ; buf->size = size ; buf->n = 0 ; buf->bFinalized = 0 ; buf->factor = 1.41 ; dummy = mcxRealloc ( *usrpptr , n_alloc * size , RETURN_ON_FAIL ) ; if (n_alloc && !dummy) { mcxMemDenied(stderr, "mcxBufInit", "char", n_alloc * size) ; buf->n_alloc = 0 ; return STATUS_FAIL ; } buf->n_alloc = n_alloc ; *usrpptr = dummy ; return STATUS_OK ; } void* mcxBufExtend ( mcxBuf* buf , dim n_request , mcxOnFail ON_FAIL ) { dim oldsize = buf->n ; char **usrpptr = (char **) buf->mempptr ; char* dummy ; if (buf->bFinalized) mcxErr("mcxBufExtend PBD", "extending finalized buffer") ; if (buf->n_alloc < buf->n + n_request) { dim n_new = MCX_MAX ( (dim) (buf->n_alloc * buf->factor + 8) , (dim) (buf->n + n_request) ) ; dummy = mcxRealloc(*usrpptr, n_new * buf->size, ON_FAIL) ; if (n_new && !dummy) { mcxMemDenied(stderr,"mcxBufExtend","char",buf->n*buf->size) ; return NULL ; } buf->n_alloc = n_new ; *usrpptr = dummy ; } buf->n += n_request ; return *usrpptr + (oldsize * buf->size) ; } dim mcxBufFinalize ( mcxBuf* buf ) { char **usrpptr = (char **) buf->mempptr ; char* dummy ; if (buf->bFinalized) mcxErr("mcxBufFinalize PBD", "extending finalized buffer") ; else buf->bFinalized = 1 ; dummy = mcxRealloc ( *usrpptr , buf->n * buf->size , RETURN_ON_FAIL ) ; if (buf->n && !dummy) { mcxMemDenied(stderr, "mcxBufFinalize", "char", buf->n * buf->size) ; errno = ENOMEM ; return buf->n ; } *usrpptr = dummy ; buf->n_alloc = buf->n ; return buf->n ; } void mcxBufReset ( mcxBuf* buf , void* mempptr ) { if (!buf->bFinalized) mcxErr("mcxBufReset PBD", "buffer not finalized") ; buf->mempptr = mempptr ; buf->n = 0 ; buf->n_alloc = 0 ; buf->bFinalized = 0 ; } /* Return a larger or equal element; the smallest of these. * The result is the minimal element at least as big as pivot. * and a 'ceil' for pivot. */ void* mcxBsearchCeil ( const void *pivot , const void *base , dim nmemb , dim size , int (*cmp)(const void *, const void *) ) { dim lft = -1 /* on purpose; we use wraparound */ ; dim rgt = nmemb ; dim bar = nmemb/2 /* nothing, or nothing that is larger than pivot */ ; if (!nmemb || cmp(pivot, ((char*)base) + (nmemb-1) * size) > 0) return NULL /* invariant: lft points to a * a member that is smaller than pivot or it * points before the first member. */ ; while (lft+1 < rgt) { /* bar is smaller than pivot, move lft inward */ if (cmp(pivot, ((char*) base) + bar*size) > 0) lft = bar /* bar is larger or equal element, move rgt inward */ ; else rgt = bar /* update bar to be the middle of lft and rgt * when lft == -1 this depends on unsigned wraparound. */ ; bar = rgt - (rgt-lft) / 2; ; } return (((char*) base) + bar * size) ; } /* Return a smaller or equal element; the largest of these. * The result is the maximal element not exceeding pivot, * and a 'floor' for pivot. */ void* mcxBsearchFloor ( const void *pivot , const void *base , dim nmemb , dim size , int (*cmp)(const void *, const void *) ) { dim lft = 0 ; dim rgt = nmemb ; dim bar = nmemb / 2 /* nothing, or nothing that is smaller than pivot */ ; if (!nmemb || cmp(pivot, base) < 0) return NULL /* invariant: rgt points to a * a member that is larger than pivot or it * points beyond the last member. */ ; while (lft+1 < rgt) { /* bar is greater than pivot, move right inward */ if (cmp(pivot, ((char*) base) + bar*size) < 0) rgt = bar /* bar is smaller than (or equal to) pivot element, move lft inward */ ; else lft = bar /* update bar to be the middle of lft and rgt */ ; bar = lft + (rgt-lft) / 2; ; } return (((char*) base) + bar * size) ; } /* TODO: compare with std::lower_bound implementation template fwd_it lower_bound(fwd_it first, fwd_it last, const t & val) { typedef typename iterator_traits::difference_type distance; distance len = std::distance(first, last); distance half; fwd_it middle; while (len > 0) { half = len >> 1; middle = first; std::advance(middle, half); if (*middle < val) { first = middle; ++first; len = len - half - 1; } else len = half; } return first; } */ double mcxMedian ( void* base , dim n , dim sz , double (*get)(const void*) , double* iqr ) { double median = 0.0, q1 = 0.0, q2 = 0.0, quant = 0.0 ; if (n > 1) median = (get((char*) base + sz * (n/2)) + get((char*) base+ sz * ((n-1)/2))) / 2.0 ; else if (n == 1) median = get(base) /* p locates the left boundary of quantile, * q locates the right boundary. We need to interpolate * neighbours in case the boundaries don't fall exacly * on integer offsets. In that case pLoffset and rOffset * are different and a weighted mean between them * is computed. */ ; if (n > 1) { dim n3 = 3 * n ; dim pLoffset = n / 4 ; dim pRoffset = pLoffset + 1 ; double pLweight = (4 - (n % 4)) / 4.0 ; double pRweight = 1.0 - pLweight ; dim qRoffset = (n3 - (n3 % 4)) / 4 ; dim qLoffset = qRoffset - 1 ; double qRweight = (n3 % 4) / 4.0 ; double qLweight = 1 - qRweight ; q1 = pLweight * get((char*) base + sz * pLoffset) + pRweight * get((char*) base + sz * pRoffset) ; q2 = qLweight * get((char*) base + sz * qLoffset) + qRweight * get((char*) base + sz * qRoffset) ; quant = q2 - q1 ; if (quant < 0) quant = -quant ; } if (iqr) *iqr = quant ; return median ; } void mcxShuffle ( void* datap , dim nmem , dim mem_size , char* mem_cell /* should have mem_size size */ ) { dim n = nmem ; char* data = datap ; while (n > 0) { unsigned long r = (random() >> 3) % n /* Fisher-Yates shuffle */ ; if (r != n-1) { memcpy(mem_cell, data + (n-1) * mem_size, mem_size) ; memcpy(data + (n-1) * mem_size, data + r * mem_size, mem_size) ; memcpy(data + r * mem_size, mem_cell, mem_size) ; } n-- ; } } zoem-11-166/util/rand.c0000644000402500021140000002373611147246105011554 00000000000000/* (C) Copyright 2004, 2005, 2006, 2007, 2008, 2009 Stijn van Dongen * * (C) Ziggurat method Copyright 2005 Jochen Voss. * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #include #include #include #include #include "rand.h" #include "math.h" #include "types.h" unsigned long mcxSeed ( unsigned long i ) { pid_t p = getpid() ; pid_t pp = getppid() ; time_t t = time(NULL) ; unsigned long s = (p ^ p << 4 ^ p << 16 ^ p << 28) ^ (pp ^ pp << 8 ^ pp << 24) ^ (t ^ t << 12 ^ t << 20) ^ (i ^ i << 3 ^ i << 23 ^ i << 26) /* I have no solid evidence backing up the usefulness of the xors. * They won't increase entropy anyway of course. * Anyway, the xors do seem useful in order to spread input * bits out over the output space, as seen from some hashing * experiments. */ ; return s ; } /* Box-Muller transform */ double mcxNormalBoxMuller ( void ) { double a = 1.0 - (random() * 1.0) / (RAND_MAX + 1.0) ; double b = 1.0 - (random() * 1.0) / (RAND_MAX + 1.0) ; return sqrt( -2.0 * log(a)) * cos(2*3.14159265358979323846*b) ; } double mcxNormal ( void ) { return mcxNormalZiggurat() ; } double mcxNormalCut ( double radius , double stddev ) { dim d ; if (radius < 0) radius = -radius ; for (d=0;d<256;d++) { double r = stddev * mcxNormal() ; if (r >= -radius && r <= radius) return r ; } return 0.0 ; } double mcxNormalSample ( double radius , double stddev ) { int n_try = 0 ; double r = 2 * radius * (((1.0 * random()) / RAND_MAX) - 0.5) ; while (n_try++ < 1000) { double n = exp( - (r * r) / (2 * stddev * stddev)) / (2.5066282746 * stddev) ; double p = (1.0 * random()) / RAND_MAX ; if (n >= p) break ; r = 2 * radius * (((1.0 * random()) / RAND_MAX) - 0.5) ; } return r ; } /* Ziggurat method * * Copyright (C) 2005 Jochen Voss. * * For details see the following article. * * George Marsaglia, Wai Wan Tsang * The Ziggurat Method for Generating Random Variables * Journal of Statistical Software, vol. 5 (2000), no. 8 * http://www.jstatsoft.org/v05/i08/ */ /* position of right-most step */ #define PARAM_R 3.44428647676 /* tabulated values for the heigt of the Ziggurat levels */ static const double ytab[128] = { 1.000000000000 , 0.963598623011 , 0.936280813353 , 0.913041104253 , 0.892278506696 , 0.873239356919 , 0.855496407634 , 0.838778928349 , 0.822902083699 , 0.807732738234 , 0.793171045519 , 0.779139726505 , 0.765577436082 , 0.752434456248 , 0.739669787677 , 0.727249120285 , 0.715143377413 , 0.703327646455 , 0.691780377035 , 0.680482768910 , 0.669418297233 , 0.658572339120 , 0.647931876189 , 0.637485254896 , 0.627221991450 , 0.617132611532 , 0.607208517467 , 0.597441877296 , 0.587825531465 , 0.578352913803 , 0.569017984198 , 0.559815170911 , 0.550739320877 , 0.541785656682 , 0.532949739145 , 0.524227434628 , 0.515614886373 , 0.507108489253 , 0.498704867478 , 0.490400854812 , 0.482193476986 , 0.474079936010 , 0.466057596125 , 0.458123971214 , 0.450276713467 , 0.442513603171 , 0.434832539473 , 0.427231532022 , 0.419708693379 , 0.412262232120 , 0.404890446548 , 0.397591718955 , 0.390364510382 , 0.383207355816 , 0.376118859788 , 0.369097692334 , 0.362142585282 , 0.355252328834 , 0.348425768415 , 0.341661801776 , 0.334959376311 , 0.328317486588 , 0.321735172063 , 0.315211514970 , 0.308745638367 , 0.302336704338 , 0.295983912320 , 0.289686497571 , 0.283443729739 , 0.277254911560 , 0.271119377649 , 0.265036493387 , 0.259005653912 , 0.253026283183 , 0.247097833139 , 0.241219782932 , 0.235391638239 , 0.229612930649 , 0.223883217122 , 0.218202079518 , 0.212569124201 , 0.206983981709 , 0.201446306496 , 0.195955776745 , 0.190512094256 , 0.185114984406 , 0.179764196185 , 0.174459502324 , 0.169200699492 , 0.163987608600 , 0.158820075195 , 0.153697969964 , 0.148621189348 , 0.143589656295 , 0.138603321143 , 0.133662162669 , 0.128766189309 , 0.123915440582 , 0.119109988745 , 0.114349940703 , 0.109635440230 , 0.104966670533 , 0.100343857232 , 0.0957672718266 , 0.0912372357329 , 0.0867541250127 , 0.082318375932 , 0.0779304915295 , 0.0735910494266 , 0.0693007111742 , 0.065060233529 , 0.0608704821745 , 0.0567324485840 , 0.0526472709800 , 0.0486162607163 , 0.0446409359769 , 0.0407230655415 , 0.0368647267386 , 0.0330683839378 , 0.0293369977411 , 0.0256741818288 , 0.0220844372634 , 0.0185735200577 , 0.0151490552854 , 0.0118216532614 , 0.00860719483079, 0.00553245272614, 0.00265435214565 } ; /* tabulated values for 2^24 times x[i]/x[i+1], * used to accept for U*x[i+1]<=x[i] * without any floating point operations */ static const unsigned long ktab[128] = { 0 , 12590644 , 14272653 , 14988939 , 15384584 , 15635009 , 15807561 , 15933577 , 16029594 , 16105155 , 16166147 , 16216399 , 16258508 , 16294295 , 16325078 , 16351831 , 16375291 , 16396026 , 16414479 , 16431002 , 16445880 , 16459343 , 16471578 , 16482744 , 16492970 , 16502368 , 16511031 , 16519039 , 16526459 , 16533352 , 16539769 , 16545755 , 16551348 , 16556584 , 16561493 , 16566101 , 16570433 , 16574511 , 16578353 , 16581977 , 16585398 , 16588629 , 16591685 , 16594575 , 16597311 , 16599901 , 16602354 , 16604679 , 16606881 , 16608968 , 16610945 , 16612818 , 16614592 , 16616272 , 16617861 , 16619363 , 16620782 , 16622121 , 16623383 , 16624570 , 16625685 , 16626730 , 16627708 , 16628619 , 16629465 , 16630248 , 16630969 , 16631628 , 16632228 , 16632768 , 16633248 , 16633671 , 16634034 , 16634340 , 16634586 , 16634774 , 16634903 , 16634972 , 16634980 , 16634926 , 16634810 , 16634628 , 16634381 , 16634066 , 16633680 , 16633222 , 16632688 , 16632075 , 16631380 , 16630598 , 16629726 , 16628757 , 16627686 , 16626507 , 16625212 , 16623794 , 16622243 , 16620548 , 16618698 , 16616679 , 16614476 , 16612071 , 16609444 , 16606571 , 16603425 , 16599973 , 16596178 , 16591995 , 16587369 , 16582237 , 16576520 , 16570120 , 16562917 , 16554758 , 16545450 , 16534739 , 16522287 , 16507638 , 16490152 , 16468907 , 16442518 , 16408804 , 16364095 , 16301683 , 16207738 , 16047994 , 15704248 , 15472926 } ; /* tabulated values of 2^{-24}*x[i] */ static const double wtab[128] = { 1.62318314817e-08 , 2.16291505214e-08 , 2.54246305087e-08, 2.84579525938e-08 , 3.10340022482e-08 , 3.33011726243e-08 , 3.53439060345e-08, 3.72152672658e-08 , 3.89509895720e-08 , 4.05763964764e-08 , 4.21101548915e-08, 4.35664624904e-08 , 4.49563968336e-08 , 4.62887864029e-08 , 4.75707945735e-08, 4.88083237257e-08 , 5.00063025384e-08 , 5.11688950428e-08 , 5.22996558616e-08, 5.34016475624e-08 , 5.44775307871e-08 , 5.55296344581e-08 , 5.65600111659e-08, 5.75704813695e-08 , 5.85626690412e-08 , 5.95380306862e-08 , 6.04978791776e-08, 6.14434034901e-08 , 6.23756851626e-08 , 6.32957121259e-08 , 6.42043903937e-08, 6.51025540077e-08 , 6.59909735447e-08 , 6.68703634341e-08 , 6.77413882848e-08, 6.86046683810e-08 , 6.94607844804e-08 , 7.03102820203e-08 , 7.11536748229e-08, 7.19914483720e-08 , 7.28240627230e-08 , 7.36519550992e-08 , 7.44755422158e-08, 7.52952223703e-08 , 7.61113773308e-08 , 7.69243740467e-08 , 7.77345662086e-08, 7.85422956743e-08 , 7.93478937793e-08 , 8.01516825471e-08 , 8.09539758128e-08, 8.17550802699e-08 , 8.25552964535e-08 , 8.33549196661e-08 , 8.41542408569e-08, 8.49535474601e-08 , 8.57531242006e-08 , 8.65532538723e-08 , 8.73542180955e-08, 8.81562980590e-08 , 8.89597752521e-08 , 8.97649321908e-08 , 9.05720531451e-08, 9.13814248700e-08 , 9.21933373471e-08 , 9.30080845407e-08 , 9.38259651738e-08, 9.46472835298e-08 , 9.54723502847e-08 , 9.63014833769e-08 , 9.71350089201e-08, 9.79732621669e-08 , 9.88165885297e-08 , 9.96653446693e-08 , 1.00519899658e-07, 1.01380636230e-07 , 1.02247952126e-07 , 1.03122261554e-07 , 1.04003996769e-07, 1.04893609795e-07 , 1.05791574313e-07 , 1.06698387725e-07 , 1.07614573423e-07, 1.08540683296e-07 , 1.09477300508e-07 , 1.10425042570e-07 , 1.11384564771e-07, 1.12356564007e-07 , 1.13341783071e-07 , 1.14341015475e-07 , 1.15355110887e-07, 1.16384981291e-07 , 1.17431607977e-07 , 1.18496049514e-07 , 1.19579450872e-07, 1.20683053909e-07 , 1.21808209468e-07 , 1.22956391410e-07 , 1.24129212952e-07, 1.25328445797e-07 , 1.26556042658e-07 , 1.27814163916e-07 , 1.29105209375e-07, 1.30431856341e-07 , 1.31797105598e-07 , 1.33204337360e-07 , 1.34657379914e-07, 1.36160594606e-07 , 1.37718982103e-07 , 1.39338316679e-07 , 1.41025317971e-07, 1.42787873535e-07 , 1.44635331499e-07 , 1.46578891730e-07 , 1.48632138436e-07, 1.50811780719e-07 , 1.53138707402e-07 , 1.55639532047e-07 , 1.58348931426e-07, 1.61313325908e-07 , 1.64596952856e-07 , 1.68292495203e-07 , 1.72541128694e-07, 1.77574279496e-07 , 1.83813550477e-07 , 1.92166040885e-07 , 2.05295471952e-07, 2.22600839893e-07 } ; double mcxNormalZiggurat ( void ) { unsigned long U, sign, i, j ; double x = 0.0, y ; while (1) { U = random() ; i = U & 0x0000007F /* 7 bit to choose the step */ ; sign = U & 0x00000080 /* 1 bit for the sign */ ; j = random() & 0x00FFFFFF /* 24 bit for the x-value */ ; x = j*wtab[i] ; if (j < ktab[i]) break ; if (i<127) { double y0, y1 ; y0 = ytab[i] ; y1 = ytab[i+1] ; y = y1+(y0-y1) * mcxUniform0 ; } else { x = PARAM_R - log(mcxUniform1)/PARAM_R ; y = exp(-PARAM_R*(x-0.5*PARAM_R)) * mcxUniform0 ; } if (y < exp(-0.5*x*x)) break ; } return sign ? x : -x ; } zoem-11-166/util/equate.c0000644000402500021140000000551111147246014012102 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #include #include "equate.h" int dblCmp ( const void* f1 , const void* f2 ) { return ( *((double*)f1) < *((double*)f2) ? -1 : *((double*)f1) > *((double*)f2) ? 1 : 0 ) ; } int dblRevCmp ( const void* f1 , const void* f2 ) { return ( *((double*)f1) > *((double*)f2) ? 1 : *((double*)f1) < *((double*)f2) ? -1 : 0 ) ; } int fltCmp ( const void* f1 , const void* f2 ) { return ( *((float*)f1) < *((float*)f2) ? -1 : *((float*)f1) > *((float*)f2) ? 1 : 0 ) ; } int fltRevCmp ( const void* f1 , const void* f2 ) { return ( *((float*)f1) > *((float*)f2) ? 1 : *((float*)f1) < *((float*)f2) ? -1 : 0 ) ; } int intCmp ( const void* i1 , const void* i2 ) { return ( *((int*)i1) - *((int*)i2)) ; } int intRevCmp ( const void* i1 , const void* i2 ) { return ( *((int*)i2) - *((int*)i1)) ; } int intnCmp ( const int* i1 , const int* i2 , int n ) { const int* i1max = i1+n ; while (i1 *((int*) i2) ); ; } int intGq ( const void* i1 , const void* i2 ) { return ( *((int*) i1) >= *((int*) i2) ); ; } int fltLt ( const void* f1 , const void* f2 ) { return ( *((float*) f1) < *((float*) f2) ); ; } int fltLq ( const void* f1 , const void* f2 ) { return ( *((float*) f1) <= *((float*) f2) ); ; } int fltGt ( const void* f1 , const void* f2 ) { return ( *((float*) f1) > *((float*) f2) ); ; } int fltGq ( const void* f1 , const void* f2 ) { return ( *((float*) f1) >= *((float*) f2) ); ; } zoem-11-166/util/opt.c0000644000402500021140000005325511361570644011437 00000000000000/* (C) Copyright 2002, 2003, 2004, 2005, 2006 Stijn van Dongen * (C) Copyright 2007, 2008, 2009, 2010 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ /* TODO * does display skip account for hidden options? */ #include #include #include #include #include "opt.h" #include "alloc.h" #include "types.h" #include "ding.h" #include "err.h" #include "equate.h" #include "minmax.h" #include "compile.h" static int strcmp_void ( const void* s1 , const void* s2 ) { return strcmp(s1, s2) ; } mcxHash* mcxOptHash ( mcxOptAnchor* opts , mcxHash* hash ) { mcxOptAnchor* anch = opts ? opts+0 : NULL ; hash = hash ? hash : mcxHashNew ( 100 , mcxStrHash , strcmp_void ) ; if (!hash) return NULL ; while (anch && anch->tag) { mcxKV* kv = mcxHashSearch(anch->tag, hash, MCX_DATUM_INSERT) ; if (!kv) { mcxHashFree(&hash, NULL, NULL) ; return NULL ; } if (kv->val) mcxErr ( "mcxOptHash" , "warning: option <%s> already present" , anch->tag ) ; kv->val = anch ; anch++ ; } return hash ; } void mcxOptHashFree ( mcxHash** hashpp ) { mcxHashFree(hashpp, NULL, NULL) ; } void* mcxOptInit ( void* opt ) { mcxOption* option = opt ; option->anch = NULL ; option->val = NULL ; return option ; } mcxOptAnchor* mcxOptFind ( char* tag , mcxHash* hopts ) { mcxKV* kv = mcxHashSearch(tag, hopts, MCX_DATUM_FIND) ; return kv ? (mcxOptAnchor*) kv->val : NULL ; } mcxOption* mcxOptParse__ ( mcxHash* opthash , char** argv , int argc , int prefix /* skip these */ , int suffix /* skip those too */ , int* n_elems_read , mcxstatus* status ) { char** argp = argv+prefix ; char** argl = argv+argc-suffix /* arg last */ ; mcxbool do_exhaust = n_elems_read ? TRUE : FALSE /* fixme: very ugly internal iface*/ ; mcxOption* opts = mcxNAlloc (argc+1, sizeof(mcxOption), mcxOptInit, RETURN_ON_FAIL) ; mcxOption* opt = opts ; if (!opts) { *status = MCX_OPT_STATUS_NOMEM ; return NULL ; } *status = MCX_OPT_STATUS_OK ; if (do_exhaust) *n_elems_read = 0 ; while (argp < argl) { char* arg = *argp ; const char* embedded_val = NULL ; mcxKV* kv = mcxHashSearch(arg, opthash, MCX_DATUM_FIND) ; mcxOptAnchor* anch = kv ? (mcxOptAnchor*) kv->val : NULL ; const char* eq = strchr(arg, '=') ; if (!kv && eq) { char argcpy[501] ; if (eq - arg < 500) { strncpy(argcpy, arg, (eq-arg)) ; argcpy[eq-arg] = '\0' ; if ( !strncmp(argcpy, "--", 2) && (kv = mcxHashSearch(argcpy+1, opthash, MCX_DATUM_FIND)) && (anch = (mcxOptAnchor*) kv->val) ) embedded_val = eq+1 ; else kv = NULL ; } else { /* fimxe do sth */ } } ; if (kv) { opt->anch = anch ; if (do_exhaust) (*n_elems_read)++ ; if (embedded_val) opt->val = embedded_val ; else if (anch->flags & MCX_OPT_HASARG) { argp++ ; if (argp >= argl) { mcxErr("mcxOptParse", "option <%s> takes value", anch->tag) ; *status = MCX_OPT_STATUS_NOARG ; break ; } opt->val = *argp /* mq note: shallow copy */ ; if (do_exhaust) (*n_elems_read)++ ; } } else { if (do_exhaust) break ; else { mcxErr("mcxOptParse", "unsupported option <%s>", arg) ; *status = MCX_OPT_STATUS_UNKNOWN ; break ; } } argp++ ; opt++ ; } if (*status) mcxOptFree(&opts) ; return opts ; } mcxOption* mcxOptExhaust ( mcxOptAnchor *anch , char **argv , int argc , int prefix /* skip these */ , int *n_elems_read , mcxstatus *status ) { mcxHash* opthash = mcxOptHash(anch, NULL) ; mcxOption* opts = mcxOptParse__ (opthash, argv, argc, prefix, 0, n_elems_read, status) ; mcxOptHashFree(&opthash) ; return opts ; } mcxOption* mcxOptParse ( mcxOptAnchor *anch , char **argv , int argc , int prefix /* skip these */ , int suffix /* skip those too */ , mcxstatus *status ) { mcxHash* opthash = mcxOptHash(anch, NULL) ; mcxOption* opts = mcxOptParse__(opthash, argv, argc, prefix, suffix, NULL, status) ; mcxOptHashFree(&opthash) ; return opts ; } mcxOption* mcxHOptExhaust ( mcxHash *opthash , char **argv , int argc , int prefix /* skip these */ , int *n_elems_read , mcxstatus *status ) { return mcxOptParse__ (opthash, argv, argc, prefix, 0, n_elems_read, status) ; } mcxOption* mcxHOptParse ( mcxHash *opthash , char **argv , int argc , int prefix /* skip these */ , int suffix /* skip those too */ , mcxstatus *status ) { return mcxOptParse__(opthash, argv, argc, prefix, suffix, NULL, status) ; } void mcxOptFree ( mcxOption** optpp ) { if (*optpp) mcxFree(*optpp) ; *optpp = NULL ; } void mcxUsage ( FILE* fp , const char* caller , const char** lines ) { int i = 0 ; while(lines[i]) { fprintf(fp, "%s\n", lines[i]) ; i++ ; } fprintf(fp, "[%s] Printed %d lines\n", caller, i+1) ; } static int (*rltFunctions[8])(const void* f1, const void* f2) = { intGt , intGq , fltGt, fltGq , intLt , intLq , fltLt, fltLq } ; int mcxOptPrintDigits = 5; const char* rltSigns[8] = { "(", "[", "(", "[" , ")", "]", ")", "]" } ; /* * todo: NULL lftbound argument & non-NULL lftRelate argument * idem for rgt */ static int checkBoundsUsage ( unsigned char type , void* var cpl__unused , int (*lftRlt) (const void*, const void*) , void* lftBound , int (*rgtRlt) (const void*, const void*) , void* rgtBound ) { int i ; const char* me = "checkBoundsUsage PBD" ; if (type != 'f' && type != 'i') { mcxErr(me, "unsupported checkbound type <%c>", type) ; return 1 ; } if ((lftRlt && !lftBound)||(!lftRlt && lftBound)) { mcxErr(me, "abusive lftRlt lftBound combination") ; return 1 ; } if ((rgtRlt && !rgtBound)||(!rgtRlt && rgtBound)) { mcxErr(me, "abusive rgtRlt rgtBound combination") ; return 1 ; } if (lftRlt) { for(i=0;i<4;i++) if (lftRlt == rltFunctions[i]) break ; if (i == 4) { mcxErr(me, "lftRlt should use gt or gq arg") ; return 1 ; } ; } if (rgtRlt) { for(i=4;i<8;i++) if (rgtRlt == rltFunctions[i]) break ; if (i==8) { mcxErr(me, "rgtRlt should use lt or lq arg") ; return 1 ; } ; } return 0 ; } /* returns * STATUS_OK for matching bounds * STATUS_FAIL for non-matching bounds * STATUS_CB_PBD for internal error. */ enum { STATUS_CB_PBD = STATUS_UNUSED + 1 } ; static mcxstatus checkBounds ( unsigned char type , void* var , int (*lftRlt) (const void*, const void*) , void* lftBound , int (*rgtRlt) (const void*, const void*) , void* rgtBound ) { int lftOk, rgtOk ; if (checkBoundsUsage(type, var, lftRlt, lftBound, rgtRlt, rgtBound)) { mcxErr("checkBounds PBD", "internal error -- cannot validate") ; return STATUS_CB_PBD ; } lftOk = !lftRlt || lftRlt(var, lftBound) ; rgtOk = !rgtRlt || rgtRlt(var, rgtBound) ; return (lftOk && rgtOk) ? STATUS_OK : STATUS_FAIL ; } static mcxTing* checkBoundsRange ( unsigned char type , void* var cpl__unused , int (*lftRlt) (const void*, const void*) , void* lftBound , int (*rgtRlt) (const void*, const void*) , void* rgtBound ) { mcxTing* textRange = mcxTingEmpty(NULL, 40) ; char* lftToken = (char *) "" ; int i ; if (!textRange) return NULL ; if (lftRlt) { for(i=0;i<4;i++) if (lftRlt == rltFunctions[i]) break ; if (i<4) lftToken = (char *) rltSigns[i] ; } else lftToken = (char *) "(" ; mcxTingPrint(textRange, "%s", lftToken) /* * This might fail due to mem shortage; * we ignore and simply keep plodding on with more mcxTingPrint-s * below. It's actually pretty inconceivable, since we alloced * 40 bytes - it depends on mcxOptPrintDigits. */ ; if (lftBound) { if (type == 'f') mcxTingPrintAfter (textRange, "%.*f", mcxOptPrintDigits, *((float*)lftBound)) ; else if (type == 'i') mcxTingPrintAfter(textRange, "%d", *((int*)lftBound)) ; } else mcxTingPrintAfter(textRange, "%s", "<-") ; mcxTingPrintAfter(textRange, "%s", ",") ; if (rgtBound) { if (type == 'f') mcxTingPrintAfter (textRange, "%.*f", mcxOptPrintDigits, *((float*)rgtBound)) ; else if (type == 'i') mcxTingPrintAfter(textRange, "%d", *((int*)rgtBound)) ; } else mcxTingPrintAfter(textRange, "%s", "->") ; if (rgtRlt) { for(i=4;i<8;i++) if (rgtRlt == rltFunctions[i]) break ; if (i<8) rgtToken = (char *) rltSigns[i] ; } else rgtToken = (char *) ")" ; mcxTingPrintAfter(textRange, "%s", rgtToken) ; return textRange ; } mcxbool mcxOptCheckBounds ( const char* caller , const char* flag , unsigned char type , void* var , int (*lftRlt) (const void*, const void*) , void* lftBound , int (*rgtRlt) (const void*, const void*) , void* rgtBound ) { mcxTing* textRange ; mcxstatus stat = checkBounds(type, var, lftRlt, lftBound, rgtRlt, rgtBound) ; if (stat == STATUS_CB_PBD) { mcxErr("mcxOptCheckBounds", "cannot validate option %s", flag) ; return FALSE ; } else if (stat == STATUS_FAIL) { if (! ( textRange = checkBoundsRange ( type , var , lftRlt , lftBound , rgtRlt , rgtBound ) ) ) return FALSE ; mcxErr ( caller , "%s argument to %s should be in range %s" , type == 'i' ? "integer" : type == 'f' ? "float" : "MICANS" , flag , textRange->str ) ; mcxTingFree(&textRange) ; return FALSE ; } return TRUE ; } int mcxOptAnchorCmpId ( const void *a1 , const void *a2 ) { const mcxOptAnchor* A1 = a1 ; const mcxOptAnchor* A2 = a2 ; return A1->id < A2->id ? -1 : A1->id - A2->id ; } int mcxOptAnchorCmpTag ( const void *a1 , const void *a2 ) { const mcxOptAnchor* A1 = a1 ; const mcxOptAnchor* A2 = a2 ; return A1->tag && A2->tag ? strcmp(A1->tag, A2->tag) : A1->tag ? -1 : 1 ; } void mcxOptAnchorSortByTag ( mcxOptAnchor *anchors , dim n_anchors ) { if (n_anchors) qsort(anchors, n_anchors, sizeof(mcxOptAnchor), mcxOptAnchorCmpTag) ; } void mcxOptAnchorSortById ( mcxOptAnchor *anchors , dim n_anchors ) { if (n_anchors) qsort(anchors, n_anchors, sizeof(mcxOptAnchor), mcxOptAnchorCmpId) ; } void parse_descr ( const char* field , const char** descrp , const char** markp , int* mark_width ) { const char* m = strstr(field, "\tM") ; const char* n = m ? strstr(m+2, "\t") : NULL ; const char* d = strstr(field, "\tD") ; if (m && n) *mark_width = n - m - 2 /* truncintok */ , *markp = m + 2 ; else *markp = "" , *mark_width = 0 ; *descrp = d ? d + 2 : field ; } void mcxOptApropos ( FILE* fp , const char* me cpl__unused , const char* syntax , int width , mcxbits display , const mcxOptAnchor opt[] ) { const mcxOptAnchor *baseopt = opt ; mcxTing* scr = mcxTingEmpty(NULL, 100) ; int id_prev = -1 ; const char* descr_usage, *descr_mark ; int mark_width = 0, mark_width_max = 0 ; int mywidth = 0 ; if (syntax) fprintf(fp, "%s\n\n", syntax) ; for (opt = baseopt; opt->tag; opt++) { int thislen = strlen(opt->tag) /* truncintok */ ; if (opt->descr_arg) thislen += 1 + strlen(opt->descr_arg) /* truncintok */ ; if ( !(opt->flags & MCX_OPT_HIDDEN) || display & MCX_OPT_DISPLAY_HIDDEN ) mywidth = MCX_MAX(mywidth, thislen) ; if (opt->descr_usage) { parse_descr (opt->descr_usage, &descr_usage, &descr_mark, &mark_width) ; mark_width_max = MCX_MAX(mark_width_max, mark_width) ; } } if (!width) width = mywidth ; for (opt = baseopt; opt->tag; opt++) { const char* skip = "" ; if ( opt->flags & MCX_OPT_HIDDEN && !(display & MCX_OPT_DISPLAY_HIDDEN) ) { id_prev = opt->id ; continue ; } if (display & MCX_OPT_DISPLAY_SKIP && opt->id - id_prev > 1) skip = "\n" ; id_prev = opt->id ; if (opt->flags & MCX_OPT_HASARG && opt->descr_arg) mcxTingPrint ( scr , "%s%c%s" , opt->tag , ' ' , opt->descr_arg ) ; else mcxTingPrint(scr, "%s", opt->tag) ; fputs(skip, fp) ; if (!opt->descr_usage) { fprintf(fp, "%s\n", scr->str) ; continue ; } if (mark_width_max) { parse_descr (opt->descr_usage, &descr_usage, &descr_mark, &mark_width) ; fprintf(fp, "%-*s", width, scr->str) ; fprintf(fp, " %-*.*s ",(int) mark_width_max,mark_width, descr_mark) ; fprintf(fp, "%s\n", descr_usage) ; } else { fprintf(fp, "%-*s", width, scr->str) ; fprintf(fp, " %s\n", opt->descr_usage) ; } } } char** mcxOptParseString ( char* src , int* argc , unsigned char delim ) { dim srclen = strlen(src) ; dim n_delim = mcxStrCountChar(src, delim, srclen) ; dim n_args = 0 ; char** argv ; char *z = src + srclen ; char *p = src, *os ; *argc = 0 ; if (!srclen) return NULL ; if (!(argv = mcxAlloc(sizeof(char*) * (n_delim+1), RETURN_ON_FAIL))) return NULL ; while (p=z) break ; os = p ; if (!(p = strchr(os, delim))) p = z ; *p = '\0' ; argv[n_args++] = os ; p++ ; } *argc = n_args ; return argv ; } mcxbool mcxOptIsInfo ( const char* arg , mcxOptAnchor* options ) { mcxOptAnchor* opt ; for (opt = options; opt->tag; opt++) if (!strcmp(opt->tag, arg)) break ; return (opt->tag && opt->flags & MCX_OPT_INFO) ? TRUE : FALSE ; } mcxTing* mcxOptArgLine ( const char** argv , int argc , int quote ) { mcxTing* cl = mcxTingEmpty(NULL, 80) ; int i ; const char* ql = "*", *qr = "*" ; if (quote == '[') ql = "[", qr = "]" ; else if (quote == '{') ql = "{", qr = "}" ; else if (quote == '<') ql = "<", qr = ">" ; else if (quote == '(') ql = "(", qr = ")" ; else if (quote == '"') ql = "\"", qr = "\"" ; else if (quote == '\'') ql = "'", qr = "'" ; if (argc) mcxTingPrint(cl, "%s%s%s", ql, argv[0], qr) ; for (i=1;idisp_argc ; const char** argv = bundle->disp_argv ; const char* me = bundle->disp_name ; const char* syntax = bundle->disp_syntax ; mcxOptAnchor* dispatcher_options = bundle->disp_shared ; dim n_options= bundle->n_disp_shared ; mcxDispEntry* entry_dir= bundle->disp_table ; void (*report_version)(const char* me) = bundle->disp_version ; const char* mode_str ; mcxDispHook* hk = NULL ; mcxOption* opts, *opt ; int n_arg_read = 0 ; mcxstatus parseStatus = STATUS_FAIL ; mcxHash *clmOpts, *delgOpts, *mergedOpts ; mcxDispEntry* entry ; int help = argc <= 1 || !strcmp(argv[1], "-h") ? 1 : 0 ; int delg_id_max ; int a ; mcxOptAnchorSortById(dispatcher_options, n_options) ; clmOpts = mcxOptHash(dispatcher_options, NULL) ; delg_id_max = dispatcher_options[n_options-1].id ; if (help) { entry = entry_dir+0 ; fprintf(stdout, "%s\n\n", syntax) ; while(entry->id >= 0) { hk = entry->get_hk() ; if (!(hk->flags & MCX_DISP_HIDDEN)) fprintf(stdout, "%s %s\n", me, hk->syntax) ; entry++ ; } fprintf ( stdout , "\n%s help (invoke manual page for )\n" "help pages are available for:" , me ) ; entry = entry_dir+0 ; while(entry->id >= 0) { hk = entry->get_hk() ; if (!(hk->flags & MCX_DISP_HIDDEN) && (hk->flags & MCX_DISP_MANUAL)) fprintf(stdout, " %s", hk->name) ; entry++ ; } fputc('\n', stdout) ; exit(0) ; } else if (argc > 1 && !strcmp(argv[1], "--version")) { report_version(me) ; exit(0) ; } else if (argc > 1 && !strcmp(argv[1], "help")) { mcxTing* minime = mcxTingNew(me) ; if (argc != 3) mcxDie ( 1 , me , "help mode requires single trailing mode argument, e.g. %s help %s" , me, (entry_dir+0)->get_hk()->name ) ; entry = entry_dir+0 /* todo unify all entry walking code */ ; while (entry->id >= 0) { hk = entry->get_hk() ; if (!strcmp(hk->name, argv[2])) { mcxTingPrintAfter(minime, "%s", hk->name) ; execlp("man", "man", minime->str, NULL) ; mcxErr(minime->str, "the 'man' program was not found") ; mcxDie(1, me, "make sure PATH is set correctly") ; } entry++ ; } if (entry->id < 0) mcxDie(1, me, "unknown mode <%s>", argv[2]) ; } /* todo emit warning to check for right version of manual page */ mode_str = argv[1] /* Find the mode in which we are invoked */ ; { const char* name ; entry = entry_dir+0 ; while (entry->id >= 0) { hk = entry->get_hk() ; name = hk->name ; if (!strcmp(name, mode_str)) break ; entry++ ; } if (entry->id < 0) mcxDie(1, me, "unknown mode <%s>", mode_str) ; } mcxOptAnchorSortById(hk->options, hk->n_options) /* caller screwed up: it's IDs should top the * largest ID in the shared options. */ ; if (hk->n_options && delg_id_max >= hk->options[0].id) mcxDie(1, me, "PBD option merge is pointless") ; delgOpts = mcxOptHash(hk->options, NULL) ; mergedOpts = mcxHashMerge(clmOpts, delgOpts, NULL, NULL) ; opts = mcxHOptExhaust (mergedOpts, (char**) argv, argc, 2, &n_arg_read, &parseStatus) ; a = 2 + n_arg_read /* fixme: we should be able to check n_at_most and n_at_least * right here, should we not? */ ; if (parseStatus != STATUS_OK) { mcxErr(me, "initialization failed") ; exit(1) ; } if (hk->init()) mcxDie(1, me, "initialization failed for <%s>", hk->name) ; for (opt=opts;opt->anch;opt++) { mcxOptAnchor* anch = opt->anch ; if (anch->id <= delg_id_max) { if (bundle->shared_handler(anch->id, opt->val, hk, bundle)) mcxDie(1, me, "dispatcher curtains") ; } else if (hk->arg_cb(anch->id, opt->val)) mcxDie(1, me, "dispatchee curtains") ; } /* do the checks below after parsing: * Parsing is needed to -h --help type flags * and other type of meta-enquiry options. */ if ( a + hk->n_at_least > argc || (hk->n_at_most >= 0 && a + hk->n_at_most < argc) ) { mcxTing* t = mcxTingPrint ( NULL , "mode %s needs %s %d trailing arguments" , mode_str , hk->n_at_least == hk->n_at_most ? "exactly" : "at least" , hk->n_at_least ) ; if (hk->n_at_most > hk->n_at_most) mcxTingPrintAfter(t, " and at most %d", hk->n_at_most) ; if (hk->n_at_most >= 0 && a + hk->n_at_most < argc) mcxTingPrintAfter(t, " (found %s)", argv[a]) ; mcxDie(1, me, "%s", t->str) ; } mcxOptFree(&opts) ; mcxOptHashFree(&clmOpts) ; mcxOptHashFree(&delgOpts) ; mcxOptHashFree(&mergedOpts) ; return hk->main(argc-a, argv+a) ; } zoem-11-166/util/io.c0000644000402500021140000006037711477735544011261 00000000000000/* (C) Copyright 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #define DEBUG 0 /* NOTE * Very few routines should be allowed to touch buffer. * create/free routines, and step and stepBack. * currently many routines ignore the buffer (but warn * when doing so). * mcxIOtryCookie is currently only one filling buffer. * Conceivably, mcxIOfind could be next. * * TODO * buffering: document, who can initiate it? * buffering: document, which routines are incompatible? * general: remove dependency on ungetc. * make mcxIOreadLine/ mcxIOstep zlib-aware. * mcxIOfind can be made much faster. * - inline fillpatbuf * - get rid of modulus computations - subtract patlen if necessary. * - use buffered input. */ #include #include #include #include #include #include #include #include #include "io.h" #include "types.h" #include "ting.h" #include "ding.h" #include "err.h" #include "alloc.h" #include "compile.h" #include "getpagesize.h" #define inbuffer(xf) (xf->buffer_consumed < xf->buffer->len) static void buffer_empty ( mcxIO* xf ) { mcxTingEmpty(xf->buffer, getpagesize()) /* sets xf->buffer->len to 0 */ ; xf->buffer_consumed = 0 ; } static void buffer_spout ( mcxIO* xf , const char* me ) { mcxErr ( "mcxIO" , "warning: reader %s in file <%s> discards buffered input <%.*s>" , me , xf->fn->str , (int) (xf->buffer->len - xf->buffer_consumed) , xf->buffer->str+xf->buffer_consumed ) ; buffer_empty(xf) ; } int begets_stdio ( const char* name , const char* mode ) { if ( ( strchr(mode, 'r') && !strcmp(name, "-") ) || ( (strchr(mode, 'w') || strchr(mode, 'a')) && (!strcmp(name, "-") || !strcmp(name, "stderr")) ) ) return 1 ; return 0 ; } static int mcxIOwarnOpenfp ( mcxIO* xf , const char* who ) { if (xf->fp && !xf->stdio) { mcxIOerr(xf, who, "has open file pointer") ; return 1 ; } return 0 ; } mcxstatus mcxIOclose ( mcxIO* xf ) { fflush(xf->fp) ;if (!strcmp(xf->fn->str, "-") && !strcmp(xf->mode, "w") && !xf->stdio) mcxDie(1, "tst", "should not happen") ; if (xf->fp && !xf->stdio) { fclose(xf->fp) ; xf->fp = NULL ; } else if (xf->fp && xf->stdio) { int fe = ferror(xf->fp) /* fixme why not in branch above? */ ; if (fe) mcxErr("mcxIOclose", "error [%d] for [%s] stdio", fe, xf->mode) , perror("mcxIOclose") ; if (xf->ateof || feof(xf->fp)) clearerr(xf->fp) ; } /* fixme contract with usr_reset */ return mcxIOreset(xf) ; } /* note: does not touch all members, notably * usr * fn * mode * fp */ mcxstatus mcxIOreset ( mcxIO* xf ) { xf->lc = 0 ; xf->lo = 0 ; xf->lo_ = 0 ; xf->bc = 0 ; xf->ateof = 0 /* regardless of read/write */ ; buffer_empty(xf) /* xf->fp not touched; promote user care */ ; if (xf->usr && xf->usr_reset) return xf->usr_reset(xf->usr) ; return STATUS_OK ; } void mcxIOerr ( mcxIO* xf , const char *complainer , const char *complaint ) { if (!xf) return ; mcxErr ( complainer , "%s stream <%s> %s" , xf->mode , xf->fn->str , complaint ) ; } mcxIO* mcxIOnew ( const char* str , const char* mode ) { if (!str || !mode) { mcxErr("mcxIOnew PBD", "void string or mode argument") ; return NULL ; } return mcxIOrenew(NULL, str, mode) ; } /* fixme: the code below is mildly muddy. * The ->stdio decision (for new streams) might best be made * at open time? */ mcxIO* mcxIOrenew ( mcxIO* xf , const char* name , const char* mode ) { mcxbool twas_stdio = xf && xf->stdio /* it was one of STD{IN,OUT,ERR} */ ; if ( mode && !strstr(mode, "w") && !strstr(mode, "r") && !strstr(mode, "a") ) { mcxErr ("mcxIOrenew PBD", "unsupported open mode <%s>", mode) ; return NULL ; } if ( getenv("TINGEA_PLUS_APPEND") && ( name && (uchar) name[0] == '+' ) && ( mode && strchr(mode, 'w') ) ) { name++ /* user can specify -o +foo to append to foo */ ; mode = "a" ; } if (!xf) /* case 1) create a new one */ { if (!name || !mode) { mcxErr("mcxIOrenew PBD", "too few arguments") ; return NULL ; } if (!(xf = (mcxIO*) mcxAlloc(sizeof(mcxIO), RETURN_ON_FAIL))) return NULL ; if (!(xf->fn = mcxTingEmpty(NULL, 20))) return NULL ; if (!(xf->buffer = mcxTingEmpty(NULL, getpagesize()))) return NULL ; xf->fp = NULL ; xf->mode = NULL ; xf->usr = NULL ; xf->usr_reset = NULL ; xf->buffer_consumed = 0 ; } else if (xf->stdio) /* case 2) have one, don't close */ NOTHING ; else if (mcxIOwarnOpenfp(xf, "mcxIOrenew")) mcxIOclose(xf) /* case 3) have one, warn and close if open */ ; mcxIOreset(xf) ; if (name && !mcxTingWrite(xf->fn, name)) return NULL ; if (mode) { if (xf->mode) mcxFree(xf->mode) ; xf->mode = mcxStrDup(mode) ; } xf->stdio = begets_stdio(xf->fn->str, xf->mode) /* name changed, no longer stdio */ ; if (twas_stdio && !xf->stdio) xf->fp = NULL ; if (xf->stdio && mode && strchr(mode, 'a')) /* recently added */ { if (xf->mode) mcxFree(xf->mode) ; xf->mode = mcxStrDup("w") ; } return xf ; } mcxstatus mcxIOopen ( mcxIO* xf , mcxOnFail ON_FAIL ) { const char* fname = xf->fn->str ; if (!xf) { mcxErr("mcxIOnew PBD", "received void object") ; if (ON_FAIL == RETURN_ON_FAIL) return STATUS_FAIL ; exit(1) ; } if (mcxIOwarnOpenfp(xf, "mcxIOopen PBD")) return STATUS_OK ; if (!strcmp(fname, "-")) { if (strchr(xf->mode, 'r')) xf->fp = stdin ; else if (strchr(xf->mode, 'w') || strchr(xf->mode, 'a')) xf->fp = stdout ; } else if ( !strcmp(fname, "stderr") && (strchr(xf->mode, 'w') || strchr(xf->mode, 'a')) ) xf->fp = stderr ; else if ((xf->fp = fopen(fname, xf->mode)) == NULL) { if (ON_FAIL == RETURN_ON_FAIL) return STATUS_FAIL ; mcxIOerr(xf, "mcxIOopen", "cannae be opened") ; mcxExit(1) ; } return STATUS_OK ; } mcxstatus mcxIOtestOpen ( mcxIO* xf , mcxOnFail ON_FAIL ) { if (!xf->fp && mcxIOopen(xf, ON_FAIL) != STATUS_OK) { mcxErr ("mcxIO", "cannot open file <%s> in mode %s", xf->fn->str, xf->mode) ; return STATUS_FAIL ; } return STATUS_OK ; } void mcxIOrelease ( mcxIO* xf ) { if (xf) { mcxIOclose(xf) ; if (xf->fn) mcxTingFree(&(xf->fn)) ; if (xf->mode) mcxFree(xf->mode) ; } } mcxstatus mcxIOappendName ( mcxIO* xf , const char* suffix ) { if (xf->fp && !xf->stdio) mcxErr ( "mcxIOappendName PBD" , "stream open while request for name change from <%s> to <%s>" , xf->fn->str , suffix ) ; else if (!mcxTingAppend(xf->fn, suffix)) return STATUS_FAIL ; xf->stdio = begets_stdio(xf->fn->str, "-") ; return STATUS_OK ; } #if 0 mcxstatus mcxIOnewName ( mcxIO* xf , const char* newname ) { if (!mcxTingEmpty(xf->fn, 0)) return STATUS_FAIL ; return mcxIOappendName(xf, newname) ; } #else mcxstatus mcxIOnewName ( mcxIO* xf , const char* newname ) { return mcxIOrenew(xf, newname, NULL) ? STATUS_OK : STATUS_FAIL ; } #endif int mcxIOstepback ( int c , mcxIO* xf ) { if (c == EOF) return EOF ; else { if (inbuffer(xf) && xf->buffer_consumed > 0) c = xf->buffer->str[--xf->buffer_consumed] /* insert a new branch for zlib aware reading here; splice into buffer */ ; else if (ungetc(c, xf->fp) == EOF) { mcxErr ( "mcxIOstepback" , "failed to push back <%d> on stream <%s>\n" , c , xf->fn->str ) ; return EOF ; } xf->bc-- ; if (c == '\n') xf->lc-- , xf->lo = xf->lo_ , xf->lo_ = 0 ; else xf->lo-- ; } return c ; } int mcxIOstep ( mcxIO* xf ) { int c #if 0 ;if (xf->buffer) fprintf(stderr, "buffer [%s]\n", xf->buffer->str) ;else fprintf(stderr, "nobuffer\n") #endif ; if (xf->ateof) c = EOF ; else if (inbuffer(xf)) { c = xf->buffer->str[xf->buffer_consumed++] ; if (!inbuffer(xf)) buffer_empty(xf) ; } else c = fgetc(xf->fp) ; switch(c) { case '\n' : xf->lc++ ; xf->bc++ ; xf->lo_ = xf->lo ; xf->lo = 0 ; break ; case EOF : xf->ateof = 1 ; break ; default : xf->bc++ ; xf->lo++ ; break ; } return c ; } /* fixme todo * * look at bc; substract it from sz (we might have read a part already). * * support growing files. and look at other items in the grep source code. */ mcxstatus mcxIOreadFile ( mcxIO *xf , mcxTing *filetxt ) { struct stat mystat ; size_t sz = 4096 ; ssize_t r ; const char* me = "mcxIOreadFile" ; mcxTingEmpty(filetxt, 0) ; if (inbuffer(xf)) buffer_spout(xf, me) ; if (!xf->stdio) { if (stat(xf->fn->str, &mystat)) mcxIOerr(xf, me, "cannae stat file") ; else sz = mystat.st_size ; } if (!xf->fp && mcxIOopen(xf, RETURN_ON_FAIL)) { mcxIOerr(xf, me, "cannae open file") ; return STATUS_FAIL ; } if (xf->ateof) return STATUS_OK /* fixme; ting count overflow */ ; if (!(filetxt = mcxTingEmpty(filetxt, sz))) return STATUS_NOMEM ; while ((r = mcxIOappendChunk(xf, filetxt, sz, 0)) > 0 && !xf->ateof) ; if (r <0) return STATUS_FAIL /* fixme; look closer at error */ ; return STATUS_OK ; } static dim mcxIO__rl_fillbuf__ ( mcxIO* xf , char* buf , dim size , int* last ) { int a = 0 ; dim ct = 0 ; while(ctateof = 1 ; return z #undef MCX_IORL_BSZ ; } dim mcxIOdiscardLine ( mcxIO *xf ) { int a ; dim ct = 0 ; if (!xf->fp) { mcxIOerr(xf, "mcxIOdiscardLine", "is not open") ; return 0 /* fixme; set errno? */ ; } while(((a = mcxIOstep(xf)) != '\n') && a != EOF) ct++ ; if (inbuffer(xf)) /* fixme/design check buffer for line */ buffer_spout(xf, "mcxIOdiscardLine") ; return ct ; } ofs mcxIOappendChunk ( mcxIO *xf , mcxTing *dst , dim sz , mcxbits flags cpl__unused ) { unsigned long psz = getpagesize() ; dim k = sz / psz /* fixme: size checks? */ ; dim rem = sz % psz ; ofs r = 1 /* pretend in case k == 0 */ /* mcxbool account = flags & MCX_CHUNK_ACCOUNT ? TRUE : FALSE */ ; dim offset = dst->len ; char* p ; if (!dst || !xf->fp || !mcxTingEnsure(dst, dst->len + sz)) return -1 /* fixme set some (new) errno */ ; if (k) while (k-- > 0 && (r = read(fileno(xf->fp), dst->str+dst->len, psz)) > 0) dst->len += r /* careful with unsignedness */ ; if ( r > 0 && rem > 0 && (r = read(fileno(xf->fp), dst->str+dst->len, rem)) > 0 ) dst->len += r ; dst->str[dst->len] = '\0' ; xf->bc += dst->len - offset ; for (p = dst->str+offset; pstr+dst->len; p++) { if (*p == '\n') { xf->lc++ ; xf->lo_ = xf->lo ; xf->lo = 0 ; } else xf->lo++ ; } /* fixme; what if k == 0, rem == 0 ? */ if (!r) /* fixme; other possibilities? */ xf->ateof = 1 ; return dst->len ; } mcxstatus mcxIOreadLine ( mcxIO *xf , mcxTing *dst , mcxbits flags ) { int a ; dim ll ; mcxbool chomp = flags & MCX_READLINE_CHOMP ? TRUE : FALSE ; mcxbool skip = flags & MCX_READLINE_SKIP_EMPTY ? TRUE : FALSE ; mcxbool par = flags & MCX_READLINE_PAR ? TRUE : FALSE ; mcxbool dot = flags & MCX_READLINE_DOT ? TRUE : FALSE ; mcxbool bsc = flags & MCX_READLINE_BSC ? TRUE : FALSE ; mcxbool repeat = dot || par || bsc ? TRUE : FALSE ; mcxbool continuation = FALSE ; mcxTing* line ; mcxstatus stat = STATUS_OK ; if (!xf->fp && mcxIOopen(xf, RETURN_ON_FAIL)) { mcxIOerr(xf, "mcxIOreadLine", "is not open") ; return STATUS_FAIL ; } if (xf->ateof) return STATUS_DONE ; if (!dst || !mcxTingEmpty(dst, 1)) return STATUS_NOMEM ; if (skip || par) { while((a = mcxIOstep(xf)) == '\n') NOTHING ; if (xf->ateof) return STATUS_DONE ; else mcxIOstepback(a, xf) ; } if (!(line = repeat ? mcxTingEmpty(NULL, 1) : dst)) return STATUS_NOMEM ; while (1) { ofs d = mcxIO__rl_rl__(xf, line) ; if (IO_MEM_ERROR == d) { stat = STATUS_NOMEM /* fixme grainify error/status */ ; break ; } ll = line->len ; if (!repeat) break ; else /* must append line to dst */ { if ( dot && !continuation && line->str[0] == '.' && ( ll == 2 || (ll == 3 && line->str[1] == '\r') ) /* fixme still not fully covering */ ) break /* do not attach the single-dot-line */ ; if (par && !continuation && ll == 1) break /* do not attach the second newline */ ; if (!mcxTingNAppend(dst, line->str, line->len)) { stat = STATUS_NOMEM ; break ; } continuation = bsc && (ll > 1 && *(line->str+ll-2) == '\\') ; if (continuation) mcxTingShrink(dst, -2) ; if (!par && !dot && (bsc && !continuation)) break ; if (xf->ateof) break ; } } if (repeat) mcxTingFree(&line) ; if (stat) return stat /* fixme; should we not check chomp first ? */ /* fixme _: \n\r ? */ ; if (chomp && dst->len && *(dst->str+dst->len-1) == '\n') mcxTingShrink(dst, -1) ; if (xf->ateof && !dst->len) return STATUS_DONE ; return STATUS_OK ; } void mcxIOlistParmodes ( void ) { fprintf ( stdout , "%5d vanilla mode, fetch next line\n" , MCX_READLINE_DEFAULT ) ; fprintf(stdout, "%5d chomp trailing newline\n", MCX_READLINE_CHOMP) ; fprintf(stdout, "%5d skip empty lines\n", MCX_READLINE_SKIP_EMPTY) ; fprintf(stdout, "%5d paragraph mode\n", MCX_READLINE_PAR) ; fprintf(stdout, "%5d backslash escapes newline\n", MCX_READLINE_BSC) ; fprintf ( stdout , "%5d section mode, ended by singly dot on a single line\n" , MCX_READLINE_DOT ) ; } void mcxIOpos ( mcxIO* xf , FILE* channel ) { const char* ateof = xf->ateof ? "at EOF in " : "" ; fprintf ( channel , "[mcxIO] %sstream <%s>, line <%ld>, character <%ld>\n" , ateof , xf->fn->str , (long) xf->lc , (long) xf->lo ) ; } void mcxIOfree_v ( void* xfpp ) { mcxIOfree((mcxIO**) xfpp) ; } void mcxIOfree ( mcxIO** xfpp ) { if (*xfpp) { mcxIO* xf = *xfpp ; mcxIOrelease(xf) ; mcxTingFree(&(xf->buffer)) ; if (xf->usr && xf->usr_free) xf->usr_free(xf->usr) ; mcxFree(xf) ; *xfpp = NULL ; } } mcxstatus mcxIOexpectReal ( mcxIO* xf , double* dblp , mcxOnFail ON_FAIL ) { int n_read = 0 ; int n_conv = 0 ; if (inbuffer(xf)) buffer_spout(xf, "mcxIOexpectReal") ; mcxIOskipSpace(xf) /* keeps accounting correct */ ; n_conv = fscanf(xf->fp, " %lf%n", dblp, &n_read) ; xf->bc += n_read /* fixme do fscanf error handling */ ; xf->lo += n_read ; if (1 != n_conv) { if (ON_FAIL == EXIT_ON_FAIL) { mcxIOpos(xf, stderr) ; mcxErr("parseReal", "parse error: expected to find real") ; mcxExit(1) ; } return STATUS_FAIL ; } return STATUS_OK ; } mcxstatus mcxIOexpectNum ( mcxIO* xf , long* lngp , mcxOnFail ON_FAIL ) { int n_read = 0 ; int n_conv = 0 ; mcxstatus status = STATUS_OK ; if (inbuffer(xf)) buffer_spout(xf, "mcxIOexpectNum") ; mcxIOskipSpace(xf) /* keeps accounting correct */ ; errno = 0 ; n_conv = fscanf(xf->fp, "%ld%n", lngp, &n_read) ; xf->bc += n_read /* fixme do fscanf error handling */ ; xf->lo += n_read ; if (1 != n_conv) mcxErr("mcxIOexpectNum", "parse error: expected to find integer") , status = STATUS_FAIL ; else if (errno == ERANGE) mcxErr("mcxIOexpectNum", "range error: not in allowable range") , status = STATUS_FAIL ; if (status) { mcxIOpos(xf, stderr) ; if (ON_FAIL == EXIT_ON_FAIL) mcxExit(1) ; } return status ; } int mcxIOskipSpace ( mcxIO* xf ) { int c ; while ((c = mcxIOstep(xf)) != EOF && isspace(c)) ; return mcxIOstepback(c, xf) ; } mcxbool mcxIOtryCookie ( mcxIO* xf , const uchar abcd[4] ) { uchar efgh[5] ; int n_read = fread(efgh, sizeof efgh[0], 4, xf->fp) ; int error = ferror(xf->fp) ; dim i = 0 ; if (n_read == 4) for (i=0; i<4 && abcd[i] == efgh[i]; i++) NOTHING #if 0 ;fprintf(stderr, "IN %d %d %d %d %d %d\n", i, n_read, (int) efgh[0], (int) efgh[1], (int) efgh[2], (int) efgh[3]) ;fprintf(stderr, "IN %d %d %d %d %d %d\n", i, n_read, (int) abcd[0], (int) abcd[1], (int) abcd[2], (int) abcd[3]) #endif ; if (i == 4) { xf->bc += 4 ; return TRUE ; } if (!fseek(xf->fp, -n_read, SEEK_CUR)) xf->bc += (4-n_read) ; else { mcxTingNAppend(xf->buffer, (char*) efgh, n_read) ; /* xf->bc += n_read mcxIOstep does subsequent accounting */ ; if (!error) clearerr(xf->fp) ; } return FALSE ; } mcxbool mcxIOwriteCookie ( mcxIO* xf , const uchar abcd[4] ) { dim n_written = fwrite(abcd, sizeof abcd[0], 4, xf->fp) ; if (n_written != 4) { mcxErr("mcxIOwriteCookie", "failed to write <%.4s>", abcd) ; return FALSE ; } return TRUE ; } /* fixme: newlines in str thrash correct lc/lo counting */ int mcxIOexpect ( mcxIO *xf , const char *str , mcxOnFail ON_FAIL ) { const char* s = str ; int c = 0 ; int d = 0 ; int n_trailing /* * no functional behaviour yet attached to this state change * fixme: semantics for STDIN agree between stdlib and us? */ ; while ( c = (uchar) s[0] , ( c && ( d = mcxIOstep(xf) , c == d ) ) ) s++ ; n_trailing = strlen(s) /* truncintok */ ; if (c && ON_FAIL == EXIT_ON_FAIL) { mcxErr("mcxIOexpect", "parse error: expected to see <%s>", str) ; mcxIOpos(xf, stderr) ; mcxExit(1) ; } return n_trailing ; } typedef struct { int tbl[256] ; int* circle /* circular buffer */ ; int circle_last /* circle bumper */ ; const char* pat ; int patlen ; } mcxIOpat ; static void mcxio_newpat ( mcxIOpat* md , const char* pattern ) { int i ; int *tbl = md->tbl ; const char* pat ; int patlen = strlen(pattern) /* truncintok */ ; md->circle = mcxAlloc(patlen * sizeof(int), EXIT_ON_FAIL) ; md->pat = pattern ; md->patlen = patlen ; pat = md->pat /* initialize */ ; for (i = 0; i < 256; i ++) tbl[i] = patlen ; for (i = 0; i < patlen-1; i++) tbl[(uchar) pat[i]] = patlen -i -1 #if DEBUG ; for (i=0; icircle_last = patlen -1 ; } static void mcxIOcleanpat ( mcxIOpat* md ) { mcxFree(md->circle) ; } static int fillpatbuf ( mcxIO* xfin , int shift , mcxIOpat* md ) { int c = 0 ; int z = 0 ; int patlen = md->patlen ; while (z < shift && (c = mcxIOstep(xfin)) != EOF) { int q = (md->circle_last+z+1) % patlen ; md->circle[q] = c ; z++ ; } md->circle_last = (md->circle_last+shift) % patlen ; return c ; } mcxstatus mcxIOfind ( mcxIO* xfin , const char* pat , mcxOnFail ON_FAIL ) { int j, k ; int shift, patlen ; int* tbl ; int* circle ; mcxIOpat md ; int found = 0 ; mcxio_newpat(&md, pat) ; patlen = md.patlen ; tbl = md.tbl ; circle = md.circle ; shift = patlen /* * hum. This means that empty pattern matches on empty string .. * Need to fix fillpatbuf if this should be reversed. */ ; if (!patlen) found = 1 ; else do { if (EOF == fillpatbuf(xfin, shift, &md)) break ; for ( j=md.circle_last+patlen, k=patlen-1 ; j>md.circle_last && circle[j%patlen] == (uchar) pat[k] ; j--, k-- ) NOTHING #if DEBUG fprintf (stderr ,"comparing circlebuf pos %d char [%c] with pattern pos %d char [%c]\n" ,(int) (j%patlen) ,(int) ((uchar) circle[j%patlen]) ,(int) k ,(int) pat[k] ) #endif ; if (j == md.circle_last) { found++ ; break ; } shift = tbl[circle[md.circle_last % patlen]] #if DEBUG ; fprintf ( stderr , "___ last[%d] index[%d] pivot[%c] shift[%d]\n" , (int) md.circle_last , (int) md.circle_last % patlen , (int) circle[md.circle_last % patlen] , (int) shift ) #endif ; } while (1) ; mcxIOcleanpat(&md) ; if (!found && ON_FAIL == RETURN_ON_FAIL) return STATUS_FAIL ; else if (!found) exit(EXIT_FAILURE) ; return STATUS_OK ; } dim mcxIOdiscard ( mcxIO* xf , dim amount ) { dim bsz = xf->buffer->mxl ; char* buf = xf->buffer->str ; dim n_read = 0 ; dim n_chunk = amount / bsz ; dim rem = amount - bsz * n_chunk ; dim i, n ; if (inbuffer(xf)) buffer_spout(xf, "mcxIOdiscard") ; for (i=0;ifp) ; n_read += n ; xf->bc += n ; if (n != bsz) break ; } if (i < n_chunk) return n_read ; if (rem) n = fread(buf, 1, rem, xf->fp) , n_read += n , xf->bc += n ; return n_read ; } zoem-11-166/util/err.c0000644000402500021140000001677711147246016011430 00000000000000/* (C) Copyright 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #include #include #include #include #include #include #include "err.h" #include "types.h" #include "compile.h" /* TODO unify code. */ FILE* mcxLogFILE = NULL; static FILE* mcx_fperr = NULL; static FILE* mcx_fpwarn = NULL; static FILE* mcx_fptell = NULL; mcxbits mcxLogLevel = 0; void mcx_err_f ( FILE* fp , const char *caller , const char *fmt , va_list *args ) { if (caller) fprintf(fp, "___ [%s] ", caller) ; else fprintf(fp, "___ ") ; vfprintf(fp, fmt, *args) ; fprintf(fp, "\n") ; return ; } void mcxFail ( void ) { while(1) sleep(1000) ; } void mcxDie ( int status , const char* caller , const char* fmt , ... ) { va_list args ; va_start(args, fmt) ; mcx_err_f(stderr, caller, fmt, &args) ; va_end(args) ; mcxExit(status) ; } void mcxExit ( int val ) { exit(val) ; } void mcxErrorFile ( FILE* fp ) { mcx_fperr = fp ; } void mcxTellFile ( FILE* fp ) { mcx_fptell = fp ; } void mcxLogSetFILE ( FILE* fp , mcxbool ENV_LOG ) { mcxLogFILE = fp ; if (ENV_LOG) mcxLogLevelSetByString(getenv("TINGEA_LOG_TAG")) ; } FILE* mcxLogGetFILE ( void ) { return mcxLogFILE ? mcxLogFILE : stderr ; } void mcxWarnFile ( FILE* fp ) { mcx_fpwarn = fp ; } void mcxErrf ( FILE* fp , const char *caller , const char *fmt , ... ) { va_list args ; va_start(args, fmt) ; mcx_err_f(fp, caller, fmt, &args) ; va_end(args) ; } void mcxErr ( const char *caller , const char *fmt , ... ) { FILE* fp = mcx_fperr ? mcx_fperr : stderr ; va_list args ; va_start(args, fmt) ; mcx_err_f(fp, caller, fmt, &args) ; va_end(args) ; } void mcxWarn ( const char *caller , const char *fmt , ... ) { va_list args ; if (caller) fprintf(stderr, "[%s] ", caller) ; va_start(args, fmt) ; vfprintf(stderr, fmt, args) ; fprintf(stderr, "\n") ; va_end(args) ; return ; } static void mcx_write_f ( FILE* fp , const char *caller , const char *fmt , va_list *args , ... ) { if (caller) fprintf(fp, "[%s] ", caller) ; vfprintf(fp, fmt, *args) ; fprintf(fp, "\n") ; return ; } void mcxTellf ( FILE* fp , const char *caller , const char *fmt , ... ) { va_list args ; va_start(args, fmt) ; mcx_write_f(fp, caller, fmt, &args) ; va_end(args) ; } void mcxTell ( const char *caller , const char *fmt , ... ) { FILE* fp = mcx_fptell ? mcx_fptell : stderr ; va_list args ; va_start(args, fmt) ; mcx_write_f(fp, caller, fmt, &args) ; va_end(args) ; } struct mcx_log_class_annotated { int type ; mcxbits class ; mcxbits low ; } ; struct mcx_log_class_annotated mcx_log_class_list[] = { { 'd' , MCX_LOG_DATA , MCX_LOG_DATA0 } , { 'f' , MCX_LOG_FUNC , MCX_LOG_FUNC0 } , { 'g' , MCX_LOG_GAUGE , MCX_LOG_GAUGE } , { 'i' , MCX_LOG_IO , MCX_LOG_IO } , { 'm' , MCX_LOG_MON , MCX_LOG_MON0 } , { 'n' , MCX_LOG_NETWORK , MCX_LOG_NETWORK } , { 'p' , MCX_LOG_IP , MCX_LOG_IP } , { 't' , MCX_LOG_THREAD , MCX_LOG_THREAD } , { 'A' , MCX_LOG_SLOT1 , MCX_LOG_SLOT1 } , { 'B' , MCX_LOG_SLOT2 , MCX_LOG_SLOT2 } , { 'C' , MCX_LOG_SLOT3 , MCX_LOG_SLOT3 } } ; mcxbool mcxLogGet ( mcxbits level_programmer ) { dim i ; mcxbool ok = FALSE ; for (i=0;i= (mcxLogLevel & mcx_log_class_list[i].class)) ) ; if (mcxLogLevel & MCX_LOG_OR) { if (ok) return TRUE ; } else if (!ok) /* AND, implicit or not */ return FALSE ; } return ok ; } void mcxLog2 ( const char* tag , const char* fmt , ... ) { FILE* fp = mcxLogFILE ? mcxLogFILE : stderr ; va_list args ; va_start(args, fmt) ; mcx_write_f(fp, tag, fmt, &args) ; va_end(args) ; } void mcxLog ( mcxbits level_programmer , const char* tag , const char* fmt , ... ) { FILE* fp = mcxLogFILE ? mcxLogFILE : stderr ; va_list args ; mcxbool ok = FALSE ; if (!mcxLogLevel || (mcxLogLevel & MCX_LOG_NULL)) return ; ok = mcxLogGet(level_programmer) ; if (ok) { va_start(args, fmt) ; mcx_write_f(fp, tag, fmt, &args) ; va_end(args) ; } } /* dependency with mcx_level_setnum */ static int mcx_level_parsenum ( int T , int c ) { int r = -1 ; if (c == 'x') r = 0 ; else if (c >= '1' && c <= '9') r = ((int) c) - '0' ; else mcxErr ( "mcxLogLevelSetByString" , "%c axis level [%c] parse error" , (int) T , (int) c ) ; return r ; } /* covers val -1 mcx_level_parsenum case */ static int mcx_level_setnum ( int val , mcxbits CLASS , mcxbits CLASS0 ) { mcxbits new = 0 ; if (val > 0) { new = (1 << (val-1)) * CLASS0 /* below we know that new is simply too high: e.g. new == 6 * but there are only 5 classes. * We then set new to the highest class member */ ; if (!(new & CLASS)) new = CLASS ^ (CLASS >> 1) ^ (CLASS0 >> 1) ; } return new ; } volatile sig_atomic_t mcxLogSigGuard = 0; void mcxLogSig ( int sig ) { mcxLogSigGuard = sig ; } void mcxLogLevelSetByString ( const char* str ) { dim i ; u8 str0 = str ? str[0] : 0 ; if (!str) return ; if (str0 == 'x') mcxLogLevel = 0 ; else if (str0 == '1') mcxLogLevel = MCX_LOG_VERBOSE ; else if (str0 == '8') mcxLogLevel = MCX_LOG_TERSE ; else if (str0 == '9') mcxLogLevel = MCX_LOG_TERSER ; if (strchr(str, 'V')) mcxLogLevel |= MCX_LOG_OR ; if (strchr(str, '#')) mcxLogLevel |= MCX_LOG_NULL ; if (strchr(str, '%')) BIT_OFF(mcxLogLevel, MCX_LOG_NULL) ; for (i=0;i #include #include #include #include #include "hash.h" #include "minmax.h" #include "types.h" #include "inttypes.h" #include "ting.h" #include "err.h" #include "alloc.h" #include "gralloc.h" #include "compile.h" #include "list.h" /* the distribution of bit counts over all 32-bit keys */ int promilles[32] = { 0, 0, 0, 0, 0, 0, 0, 0 , 2, 7, 15, 30, 53, 81,110,131 ,140,131,110, 81, 53, 30, 15, 7 , 2, 0, 0, 0, 0, 0, 0, 0 } ; #ifndef TINGEA_HASH_CACHE # define TINGEA_HASH_CACHE 0 #endif typedef struct hash_link { struct hash_link* next ; mcxKV kv #if TINGEA_HASH_CACHE ; u32 hv #endif ; } hash_link ; typedef struct bucket { hash_link* base ; } mcx_bucket ; /* For further optimization work, options * options * load * cmp * hash * src_link * can be shared between different hashes (e.g. * with multidimensional hashes). Consider * making src_link file static variable. */ struct mcxHash { dim n_buckets /* 2^n_bits */ ; mcx_bucket *buckets ; dim n_entries ; mcxbits options ; int (*cmp) (const void *a, const void *b) ; u32 (*hash) (const void *a) ; mcxGrim* src_link ; float load ; } ; struct mcxHashWalk { mcxHash* hash ; dim i_bucket ; hash_link* link ; } ; void* mcx_bucket_init ( void* buck ) { ((mcx_bucket*) buck)->base = NULL ; return NULL ; } void bitprint ( u32 key , FILE* fp ) ; int bitcount ( u32 key ) ; mcxHash* mcxHashNew ( dim n_buckets , u32 (*hash)(const void *a) , int (*cmp) (const void *a, const void *b) ) { mcxHash *h ; mcxbool ok = FALSE ; u8 n_bits = 0 ; if (!n_buckets) { mcxErr("mcxHashNew strange", "void alloc request") ; n_buckets = 2 ; } if (!(h = mcxAlloc(sizeof(mcxHash), RETURN_ON_FAIL))) return NULL ; while(n_buckets) { n_buckets >>= 1 ; n_bits++ ; } h->load = 0.5 ; h->n_entries = 0 ; h->n_buckets = n_buckets = (1 << n_bits) ; h->cmp = cmp ; h->hash = hash ; h->options = MCX_HASH_OPT_DEFAULTS ; h->src_link = NULL ; while (1) /* fixme 2nd arg below, have better choice? */ { h->src_link = mcxGrimNew(sizeof(hash_link), h->n_buckets, MCX_GRIM_ARITHMETIC) ; if (!h->src_link) break ; if (! ( h->buckets = mcxNAlloc ( h->n_buckets , sizeof(mcx_bucket) , mcx_bucket_init , RETURN_ON_FAIL ) ) ) break ; ok = TRUE ; break ; } if (!ok) { mcxGrimFree(&(h->src_link)) ; mcxFree(h) ; return NULL ; } return h ; } dim mcxHashMemSize ( mcxHash* hash ) { return mcxGrimMemSize(hash->src_link) + sizeof(mcx_bucket) * hash->n_buckets ; } void mcxHashGetSettings ( mcxHash* hash , mcxHashSettings* settings ) { settings->n_buckets = hash->n_buckets ; settings->load = hash->load ; settings->n_entries = hash->n_entries ; settings->options = hash->options ; } static dim hash_link_size ( hash_link* link ) { dim s = 0 ; while(link) link = link->next , s++ ; return(s) ; } void mcxHashStats ( FILE* fp , mcxHash* h ) { dim buckets = h->n_buckets ; dim buckets_used = 0 ; float ctr = 0.0 ; float cb = 0.0 ; dim max = 0 ; dim entries = 0 ; const char* me = "mcxHashStats" ; int j, k, distr[32] ; mcx_bucket *buck ; for (j=0;j<32;j++) distr[j] = 0 ; for (buck=h->buckets; buckbuckets + h->n_buckets; buck++) { dim d = hash_link_size(buck->base) ; hash_link* this= buck->base ; if (d) { buckets_used++ ; entries += d ; ctr += (float) d * d ; cb += (float) d * d * d ; max = MCX_MAX(max, d) ; } while(this) { u32 u = (h->hash)(this->kv.key) ; int ct = bitcount(u) ; this = this->next ; distr[ct]++ ;if (0) fprintf(stderr, "bucket [%d] key [%s]\n", (int)d, ((mcxTing*) this->kv.key)->str) ; } } ctr = ctr / MCX_MAX(1, entries) ; cb = sqrt(cb / MCX_MAX(1, entries)) ; if (buckets && buckets_used) mcxTellf ( fp , me , "%4.2f bucket usage (%ld available, %ld used, %ld entries)" , (double) ((double) buckets_used) / buckets , (long) buckets , (long) buckets_used , (long) entries ) , mcxTellf ( fp , me , "bucket average: %.2f, center: %.2f, cube: %.2f, max: %ld" , (double) entries / ((double) buckets_used) , (double) ctr , (double) cb , (long) max ) ; mcxTellf(fp, me, "bit distribution (promilles):") ; fprintf ( fp , " %-37s %s\n" , "Current bit distribution" , "Ideally random distribution" ) ; for (k=0;k<4;k++) { for (j=k*8;j<(k+1)*8;j++) fprintf(fp, "%3.0f ", entries ? (1000 * (float)distr[j]) / entries : 0.0) ; fprintf(fp, " "); ; for (j=k*8;j<(k+1)*8;j++) fprintf(fp, "%3d ", promilles[j]) ; fprintf(fp, "\n") ; } mcxTellf(fp, me, "link count: %ld", (long) (mcxGrimCount(h->src_link))) ; mcxTellf(fp, me, "link mem count: %ld", (long) (mcxGrimMemSize(h->src_link))) ; mcxTellf(fp, me, "done") ; } void mcxHashSetOpts ( mcxHash* h , double load , int options ) { if (options >= 0) h->options |= options /* fixme; are there states in which either of these can be corrupting ? */ ; h->load = load ; } void mcxHashFreeScalar ( void* scalar cpl__unused ) { /* this triggers freeing of kv.key or kv.val */ ; } void mcxHashFree ( mcxHash** hpp , void freekey(void* key) , void freeval(void* key) ) { mcxHash* h = *hpp ; mcx_bucket* buck = h ? h->buckets : NULL ; dim d = h ? h->n_buckets : 0 ; if (!h) return ; if (freekey || freeval) { while (d-- > 0) /* careful with unsignedness */ { hash_link* link = (buck++)->base ; while(link) { void* key = link->kv.key ; void* val = link->kv.val ; if (freekey && key) freekey(key) , mcxFree(key) ; if (freeval && val) freeval(val) , mcxFree(val) ; link = link->next ; } } } mcxGrimFree(&h->src_link) ; mcxFree(h->buckets) ; mcxFree(h) ; *hpp = NULL ; } #define MCX_HASH_DOUBLING MCX_HASH_OPT_UNUSED #if TINGEA_HASH_CACHE static hash_link* mcx_bucket_search ( mcxHash* h , void* ob , mcxmode ACTION , u32* hashval ) { u32 thishash = hashval ? *hashval : (h->hash)(ob) ; mcx_bucket *buck = h->buckets + (thishash & (h->n_buckets-1)) ; hash_link* link = buck->base, *prev = NULL, *new ; int delta = 0 ; while ( link && ( link->hv != thishash || h->cmp(ob, link->kv.key) ) ) prev = link , link = link->next ; if (link && ACTION == MCX_DATUM_DELETE) { if (buck->base == link) buck->base = link->next ; else prev->next = link->next ; delta = -1 ; mcxGrimLet(h->src_link, link) /* we return link below though */ ; } else if (!link) { if (ACTION == MCX_DATUM_FIND || ACTION == MCX_DATUM_DELETE) link = NULL ; else if (ACTION == MCX_DATUM_INSERT) { new = mcxGrimGet(h->src_link) /* fixme could be NULL */ ; new->next = NULL ; new->kv.val = NULL ; new->kv.key = ob ; new->hv = thishash ; if (!buck->base) buck->base = new /* in TINGEA_HASH_CACHE case we always append */ ; else new->next = prev->next , prev->next = new ; delta = 1 ; link = new ; } } h->n_entries += delta ; return link ; } #else static hash_link* mcx_bucket_search ( mcxHash* h , void* ob , mcxmode ACTION , u32* hashval ) { u32 thishash = hashval ? *hashval : (h->hash)(ob) ; mcx_bucket *buck = h->buckets + (thishash & (h->n_buckets-1)) ; hash_link* link = buck->base, *prev = NULL, *new ; int c = 1 ; int delta = 0 ; while ( link && (c = h->cmp(ob, link->kv.key)) > 0 ) prev = link , link = link->next ; if (!c && ACTION == MCX_DATUM_DELETE) { if (buck->base == link) buck->base = link->next ; else prev->next = link->next ; delta = -1 ; mcxGrimLet(h->src_link, link) /* we return link below though */ ; } else if (!link || c < 0) { if (ACTION == MCX_DATUM_FIND || ACTION == MCX_DATUM_DELETE) link = NULL ; else if (ACTION == MCX_DATUM_INSERT) { new = mcxGrimGet(h->src_link) /* fixme could be NULL */ ; new->next = NULL ; new->kv.val = NULL ; new->kv.key = ob ; if (!buck->base) buck->base = new ; else if (link == buck->base) new->next = buck->base , buck->base = new ; else new->next = prev->next , prev->next = new ; delta = 1 ; link = new ; } } h->n_entries += delta ; return link ; } #endif static mcxstatus mcx_hash_double ( mcxHash* h ) ; mcxKV* mcxHashSearchx ( void* key , mcxHash* h , mcxmode ACTION , int* delta ) { hash_link *link ; dim n_entries = h->n_entries ; if ( h->load * h->n_buckets < h->n_entries && !(h->options & (MCX_HASH_OPT_CONSTANT | MCX_HASH_DOUBLING)) && mcx_hash_double(h) ) mcxErr("mcxHashSearch", "cannot double hash") ; link = mcx_bucket_search(h, key, ACTION, NULL) ; if (delta) *delta = h->n_entries < n_entries ? -1 : (int) (h->n_entries - n_entries) ; return link ? &link->kv : NULL ; } enum { ARRAY_OF_KEY , ARRAY_OF_KV } ; void mcxHashApply ( mcxHash* hash , void (*cb)(const void* key, void* val, void* data) , void* data ) { mcxHashWalk* walk = mcxHashWalkInit(hash) ; mcxKV* kv ; dim i_bucket ; while ((kv = mcxHashWalkStep(walk, &i_bucket))) cb(kv->key, kv->val, data) ; mcxHashWalkFree(&walk) ; } static void** hash_array ( mcxHash* hash , dim* n_entries , int (*cmp)(const void*, const void*) , mcxbits opts cpl__unused , mcxenum mode ) { void** obs = mcxAlloc(sizeof(void*) * hash->n_entries, RETURN_ON_FAIL) ; dim d = 0 ; mcxKV* kv ; const char* me = mode == ARRAY_OF_KEY ? "mcxHashKeys" : "mcxHashKVs" ; mcxHashWalk* walk = mcxHashWalkInit(hash) ; if (!walk || !obs) return NULL ; while ((kv = mcxHashWalkStep(walk, NULL))) /* fixme extract */ { if (d >= hash->n_entries) { mcxErr ( me , "PANIC inconsistent state (n_entries %ld)" , (long) hash->n_entries ) ; break ; } obs[d] = mode == ARRAY_OF_KEY ? kv->key : kv ; d++ ; } if (d != hash->n_entries) mcxErr(me, "PANIC inconsistent state (n_entries %lu)", (ulong) hash->n_entries) ; if (cmp) qsort(obs, d, sizeof(void*), cmp) ; mcxHashWalkFree(&walk) ; *n_entries = d ; return obs ; } void** mcxHashKeys ( mcxHash* hash , dim* n_entries , int (*cmp)(const void*, const void*) , mcxbits opts /* unused yet */ ) { return hash_array(hash, n_entries, cmp, opts, ARRAY_OF_KEY) ; } void** mcxHashKVs ( mcxHash* hash , dim* n_entries , int (*cmp)(const void*, const void*) , mcxbits opts /* unused yet */ ) { return hash_array(hash, n_entries, cmp, opts, ARRAY_OF_KV) ; } mcxKV* mcxHashWalkStep ( mcxHashWalk *walk , dim *i_bucket ) { hash_link* step = walk->link ; while (!step && ++walk->i_bucket < walk->hash->n_buckets) step = (walk->hash->buckets+walk->i_bucket)->base ; if (step) { walk->link = step->next ; if (i_bucket) *i_bucket = walk->i_bucket ; return &step->kv ; } return NULL ; } mcxHashWalk* mcxHashWalkInit ( mcxHash *h ) { mcxHashWalk* walk = mcxAlloc(sizeof *walk, RETURN_ON_FAIL) ; if (!walk) return NULL ; walk->hash = h ; if (!h || !h->buckets) { mcxFree(walk) ; return NULL ; } walk->i_bucket = 0 ; walk->link = (h->buckets+0)->base ; return walk ; } void mcxHashWalkFree ( mcxHashWalk **walkpp ) { mcxFree(*walkpp) ; *walkpp = NULL ; } mcxHash* mcxHashMerge ( mcxHash* h1 , mcxHash* h2 , mcxHash* hd /* hash destination */ , void* merge(void* val1, void* val2) ) { mcxHash* ha[2] /* hash array */ ; mcxHash* h ; int i ; if (!h1 || !h2) mcxDie(1, "mcxHashMerge FATAL", "clone functionality not yet supported") /* * fixme/note I am comparing fie pointers here, is that ok? */ ; if (h1->hash != h2->hash || h1->cmp != h2->cmp) mcxErr("mcxHashMerge WARNING", "non matching hash or cmp fie") ; if (merge) mcxErr("mcxHashMerge WARNING", "merge functionality not yet supported") ; hd = hd ? hd : mcxHashNew ( h1->n_entries + h2->n_entries , h1->hash , h1->cmp ) ; if (!hd) return NULL ; ha[0] = h1 ; ha[1] = h2 ; for (i=0;i<2;i++) { h = ha[i] ; if (h != hd) { mcx_bucket* buck ; for (buck = h->buckets; buckbuckets + h->n_buckets; buck++) { hash_link* this = buck->base ; while(this) { mcxKV* kv = mcxHashSearch(this->kv.key, hd, MCX_DATUM_INSERT) ; if (!kv) return NULL /* note/fixme: cannot free hd, don't have key/val free functions */ ; if (!kv->val) kv->val = this->kv.val ; this = this->next ; } } } } return hd ; } static mcxstatus mcx_hash_double ( mcxHash* h ) { mcx_bucket* ole_bucket = h->buckets ; mcx_bucket* ole_buckets = h->buckets ; dim d = h->n_buckets ; dim n_fail = 0 ; if (h->options & MCX_HASH_DOUBLING) /* called before */ { mcxErr("mcx_hash_double PANIC", "double trouble") ; return STATUS_FAIL ; } h->options |= MCX_HASH_DOUBLING ; if (! ( h->buckets = mcxNAlloc ( 2 * h->n_buckets , sizeof(mcx_bucket) , mcx_bucket_init , RETURN_ON_FAIL ) ) ) { h->options ^= MCX_HASH_DOUBLING ; h->buckets = ole_buckets ; return STATUS_FAIL ; } h->n_buckets *= 2 ; h->n_entries = 0 ; while(d-- > 0) /* careful with unsignedness */ { hash_link* this = ole_bucket->base ; while(this) { hash_link* next = this->next, *clone ; void* val = this->kv.val ; void* key = this->kv.key ; mcxGrimLet(h->src_link, this) /* will be used immediately */ #if TINGEA_HASH_CACHE ; clone = mcx_bucket_search(h, key, MCX_DATUM_INSERT, &this->hv) #else ; clone = mcx_bucket_search(h, key, MCX_DATUM_INSERT, NULL) #endif ; if (clone) clone->kv.val = val ; else n_fail++ ; this = next ; } ole_bucket++ ; } if (n_fail) mcxErr ( "mcx_hash_double PANIC" , "<%ld> reinsertion failures in hash with <%ld> entries" , (long) n_fail , (long) h->n_entries ) ; mcxFree(ole_buckets) ; h->options ^= MCX_HASH_DOUBLING ; return STATUS_OK ; } #define BJmix(a,b,c) \ { \ a -= b; a -= c; a ^= (c>>13); \ b -= c; b -= a; b ^= (a<< 8); \ c -= a; c -= b; c ^= (b>>13); \ a -= b; a -= c; a ^= (c>>12); \ b -= c; b -= a; b ^= (a<<16); \ c -= a; c -= b; c ^= (b>> 5); \ a -= b; a -= c; a ^= (c>> 3); \ b -= c; b -= a; b ^= (a<<10); \ c -= a; c -= b; c ^= (b>>15); \ } /* * Thomas Wang says Robert Jenkins says this is a good integer hash function: *unsigned int inthash(unsigned int key) *{ * key += (key << 12); * key ^= (key >> 22); * key += (key << 4); * key ^= (key >> 9); * key += (key << 10); * key ^= (key >> 2); * key += (key << 7); * key ^= (key >> 12); * return key; *} */ /* created by Bob Jenkins */ u32 mcxBJhash ( register const void* key , register u32 len ) { register u32 a, b, c, l ; const char* k = key ; l = len ; a = b = 0x9e3779b9u ; c = 0xabcdef01u ; while (l >= 12) { a += k[0] + (k[1]<<8) + (k[2]<<16) + (k[3]<<24) ; b += k[4] + (k[5]<<8) + (k[6]<<16) + (k[7]<<24) ; c += k[8] + (k[9]<<8) + (k[10]<<16)+ (k[11]<<24) ; BJmix(a,b,c) ; k += 12 ; l -= 12 ; } c += len ; switch(l) /* all the case statements fall through */ { case 11: c+= k[10]<<24 ; case 10: c+= k[9]<<16 ; case 9 : c+= k[8]<<8 /* the first byte of c is reserved for the length */ ; case 8 : b+= k[7]<<24 ; case 7 : b+= k[6]<<16 ; case 6 : b+= k[5]<<8 ; case 5 : b+= k[4] ; case 4 : a+= k[3]<<24 ; case 3 : a+= k[2]<<16 ; case 2 : a+= k[1]<<8 ; case 1 : a+= k[0] /* case 0: nothing left to add */ ; } BJmix(a,b,c) ; return c ; } /* created by Chris Torek */ u32 mcxCThash ( const void *key , u32 len ) #define ctHASH4a h = (h << 5) - h + *k++; #define ctHASH4b h = (h << 5) + h + *k++; #define ctHASH4 ctHASH4b { u32 h = 0 ; const unsigned char *k = key ; if (len > 0) { unsigned loop = (len + 8 - 1) >> 3 /* loop >= 1 */ ; switch (len & (8 - 1)) { case 0: do { /* All fall through */ ctHASH4 case 7: ctHASH4 case 6: ctHASH4 case 5: ctHASH4 case 4: ctHASH4 case 3: ctHASH4 case 2: ctHASH4 case 1: ctHASH4 } while (--loop) /* unsignedcmpok */ ; } } ; return h ; } /* All 3 hash fies below play on a similar theme. Interesting: as long as only * << >> and ^ are used, a hash function does a partial homogeneous fill of all * 2^k different strings of length k built out of two distinct characters -- * not all buckets need be used. E.g. for k=15, such a hash function might fill * 2^13 buckets with 4 entries each, or it might fill 2^10 buckets with 32 * entries each. This was observed, not proven. */ u32 mcxSvDhash ( const void *key , u32 len ) { u32 h = 0x7cabd53e /* 0x7cabd53e */ ; const char* k = key ; h = 0x0180244a ; while (len--) { u32 g = *k ; u32 gc = 0xff ^ g ; u32 hc = 0xffffffffu ; hc ^= h ; h = ( (h << 2) + h + (h >> 3)) ^ ( (g << 25) + (gc << 18) + (g << 11) + (g << 5) + g ) ; k++ ; } ; return h ; } /* created by me */ u32 mcxSvD2hash ( const void *key , u32 len ) { u32 h = 0x7cabd53e /* 0x7cabd53e */ ; const char* k = key ; while (len--) { u32 g = *k ; u32 gc = 0xff ^ g ; h = ( (h << 3) ^ h ^ (h >> 5) ) ^ ( (g << 25) ^ (gc << 18) ^ (g << 11) ^ (gc << 5) ^ g ) ; k++ ; } ; return h ; } /* created by me */ u32 mcxSvD1hash ( const void *key , u32 len ) { u32 h = 0xeca96537u ; const char* k = key ; while (len--) { u32 g = *k ; h = ( (h << 3) ^ h ^ (h >> 5) ) ^ ( (g << 21) ^ (g << 12) ^ (g << 5) ^ g ) ; k++ ; } ; return h ; } /* created by Daniel Phillips */ u32 mcxDPhash ( const void *key , u32 len ) { u32 h0 = 0x12a3fe2du , h1 = 0x37abe8f9u ; const char* k = key ; while (len--) { u32 h = h1 + (h0 ^ (*k++ * 71523)) ; h1 = h0 ; h0 = h ; } return h0 ; } /* "GNU Emacs" hash (from m4) */ u32 mcxGEhash ( const void* key , u32 len ) { const char* k = key ; u32 hash = 0 ; int t ; while (len--) { if ((t = *k++) >= 0140) t -= 40 ; hash = ((hash << 3) + (hash >> 28) + t) ; } return hash ; } /* Fowler Noll Vo hash */ u32 mcxFNVhash ( const void *buf , u32 len ) { u32 hval = 0x811c9dc5 ; const char *bp = buf ; while (len--) { #if 0 /* other branch supposedly optimizes gcc */ hval *= 0x01000193 #else hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24) #endif ; hval ^= *bp++; ; } return hval ; } /* Berkely Database hash */ u32 mcxBDBhash ( const void *key , u32 len ) { const char* k = key ; u32 hash = 0 ; while (len--) { hash = *k++ + (hash << 6) + (hash << 16) - hash ; } return hash ; } /* One at a time hash, Bob Jenkins/Colin Plumb */ u32 mcxOAThash ( const void *key , u32 len ) { const char* k = key ; u32 hash = 0 ; while (len--) { hash += *k++ ; hash += (hash << 10) ; hash ^= (hash >> 6) ; } hash += (hash << 3); ; hash ^= (hash >> 11); ; hash += (hash << 15); ; return hash ; } /* by Dan Bernstein */ u32 mcxDJBhash ( const void *key , u32 len ) { const char* k = key ; u32 hash = 5381 ; while (len--) { hash = *k++ + (hash << 5) + hash ; } return hash ; } /* UNIX ELF hash */ u32 mcxELFhash ( const void *key , u32 len ) { const char* k = key ; u32 hash = 0 ; u32 g ; while (len--) { hash = *k++ + (hash << 4) ; if ((g = (hash & 0xF0000000u))) hash ^= g >> 24 ; hash &= ~g ; } return hash ; } u32 mcxStrHash ( const void* s ) { dim l = strlen(s) ; return(mcxDPhash(s, l)) ; } int mcxStrCmp ( const void* a , const void* b ) { return strcmp(a, b) ; } void bitprint ( u32 key , FILE* fp ) { do { fputc(key & 1 ? '1' : '0', fp) ; } while ((key = key >> 1)) ; } int bitcount ( u32 key ) { int ct = 0 ; do { if (key & 1) ct++ ; } while ((key = key >> 1)) ; return ct ; } #if 0 /* The old legacy hash */ static __u32 dx_hack_hash (const char *name, int len) { __u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9; while (len--) { __u32 hash = hash1 + (hash0 ^ (*name++ * 7152373)); if (hash & 0x80000000) hash -= 0x7fffffff; hash1 = hash0; hash0 = hash; } return (hash0 << 1); } #endif zoem-11-166/util/heap.c0000644000402500021140000000611611311741155011534 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #include #include #include "alloc.h" #include "heap.h" #include "types.h" #include "err.h" mcxHeap* mcxHeapInit ( void* h ) { mcxHeap* heap = h ; if (!heap && !(heap = mcxAlloc(sizeof(mcxHeap), RETURN_ON_FAIL))) return NULL ; heap->base = NULL ; heap->heapSize = 0 ; heap->elemSize = 0 ; heap->cmp = NULL ; heap->n_inserted = 0 ; return heap ; } mcxHeap* mcxHeapNew ( mcxHeap* h , dim heapSize , dim elemSize , int (*cmp) (const void* lft, const void* rgt) ) { mcxHeap* heap = mcxHeapInit(h) ; mcxstatus status = STATUS_FAIL ; char* base ; do { if (!heap) break ; if (!(heap->base = mcxAlloc (heapSize*elemSize, RETURN_ON_FAIL))) break ; status = STATUS_OK ; } while (0) ; if (status) { mcxHeapFree(&heap) ; return NULL ; } heap->heapSize = heapSize ; heap->elemSize = elemSize ; heap->cmp = cmp ; heap->n_inserted = 0 ; base = (char*) heap->base ; return heap ; } void mcxHeapClean ( mcxHeap* heap ) { heap->n_inserted = 0 ; } void mcxHeapRelease ( void* heapv ) { mcxHeap* heap = (mcxHeap*) heapv ; if (heap->base) mcxFree(heap->base) ; heap->base = NULL ; heap->heapSize = 0 ; } void mcxHeapFree ( mcxHeap** heap ) { if (*heap) { if ((*heap)->base) mcxFree((*heap)->base) ; mcxFree(*heap) ; *heap = NULL ; } } void mcxHeapInsert ( mcxHeap* heap , void* elem ) { char* heapRoot = heap->base ; char* elemch = elem ; dim elsz = heap->elemSize ; dim hpsz = heap->heapSize ; int (*cmp)(const void *, const void*) = heap->cmp ; if (heap->n_inserted < hpsz) { dim i = heap->n_inserted ; while (i != 0 && (cmp)(heapRoot+elsz*((i-1)/2), elemch) < 0) { memcpy(heapRoot + i*elsz, heapRoot + elsz*((i-1)/2), elsz) ; i = (i-1)/2 ; } memcpy(heapRoot + i*elsz, elemch, elsz) ; heap->n_inserted++ ; } else if ((cmp)(elemch, heapRoot) < 0) { dim root = 0 ; dim d ; while ((d = 2*root+1) < hpsz) { if ( (d+1 #include #include #include #include "let.h" #include "ting.h" #include "ding.h" #include "alloc.h" #include "minmax.h" #include "err.h" #include "types.h" #include "ding.h" #include "compile.h" /* ************************************************************************** * * ** Implementation notes (a few). * * Features * All of C's operators in a revised precedence scheme, with exponentiation * added. The groups of logical operators, bitwise operators, comparison * operators have equal precedence internally (but changing this is a * matter of editing a single table). Unsigned integers are not supported * (so bitwise complement behaves funnily). Ternary operator behaves as * should; evaluates only one of its branches. Boolean logical operators * do shortcircuit. All mathematical functions from math.h and some * additional ones (e.g. abs, round, sign). Variables can be parsed and * evaluated using user-supplied functions. Currently, variables must be * recognizable by a special lead character. Todos * I may want to pass raam along to compute and flatten after all. * This brings back in the tokids, which are nice to have. * It also means that global callbacks can be localized. * * Right now, inf is not caught. isinf() seems not portable though :( * * getatoken could be equipped with more error handling facilities now that * user_parse is inserted. The current behaviour is that parsing control * is transfered to native parsing if user parsing does not succeed. This * can be used for overloading the special character, e.g. setting it to * '!' -> user parsing could require a !<..> sequence; if not found, '!' * would be seen as the negation operator. * * user_parse and user_eval need to be global in scope as long * as raam is not passed along in compute and flatten, * but that is actually not a problem (apart from .so libs). * * Hashing of function names. * * Audit overflow, exceptions, long/double mixing. * * Should min(1,2.0) be 1 rather than 1.0 ? in that case, need special * behaviour for twoary max and min just like now for oneary abs. * * Make int to double overflow promotion a trmInit option. * * on STATUS_FAIL for parse, write error message in telraam. * * allow functions with empty arguments (e.g. rand()). * * add some of the funny stuff provided by fv, f? * * tn toktype is used both in lexing/parsing stage and in reduction stage. * not scalable. Future idea: * Implement an intermediate layer between parsing and evaluation. * E.g. convert the result of trmParse() to a stack. Done * Errors cascade back. For parse errors all memory seems to be reclaimed * (for all cases tried so far). * After parsing, no other errors should be possible I believe. * * made real type, which could be long double. Tis not however, * because long double math does not seem widespread and/or standard. * made num type, which could be long long. Tis not however, * because long long math seems to be C99 (not widespread etc). * * enabled user callbacks for variable and function interpolation. Integers/Floats * It is tracked which operations result in integers and which do * not. If integer overflow occurs the result is promoted to double. * The internal logic implementing this behaviour dictates that * as long as (flags & TN_ISINT) it must be true that fval ==~ ival. * TODO: make this customizable. * NOTE: doubles pbb can capture all 32-bit integers, but not so for * 64-bit integers. May make subtle difference. Apology * It's lame to write your own parser rather than lex and yacc but scriptor * wanted to do it one more time than zero. * * The result is pretty ad hoc and not generic, what it's got going for it * is that it works. Also, trmParse() is not that bad I believe, although * it is not very scalable either. compute() is the trickiest. Some * provisions were made to get short-circuiting and the ternary op working. * The same data structure is used for tokenization, parsing, and * evaluation. Ugly! Implementation notes * . Parse tree is implicitly stored as a linked list. * . Evaluation is done by compute/flatten; precedence and branching are done * during evaluation, rather than (partly) precomputed (which would much be * cleaner). precedence is done in flatten; branching in compute. * . tn's (token nodes) are used both by lexer, parser, and interpreter, * which is not the nicest way of doing it. * . Could push and convert all tokens to a stack (format), which would unify * operators and functions to some extent, and separate interpretation from * parsing and braching. Errors * Currently we have arithmetic error only. * TODO: * Overflow error -- but isinf does not seem portable :( Caveat * tnFree/tnDup should not be applied to a TOKEN_CLOSE node, dupwise * speaking. This is because compute currently has a sanity check for * pointer identity before and after its main loop. * * tricky spots, unfinished thoughts, future ideas, and omitted assertions * are marked with the sequence 'mq' (or even 'mqmq'), but not all of them. * Some reminders * routines that must be checked (malloc dependent) * tnDup * tnNewToken * tnPushToken * tnPushThis * routines that need be checked for other reason * tnUser * flatten * compute * getatom * getexpression * trmParse */ typedef double real; /* but we always use double arithmetic */ /* i.e. never use long double */ #ifdef LET99 typedef long long num; # define NUM_MIN LLONG_MIN /* this branch has not been tested! */ # define NUM_MAX LLONG_MAX /* and requires modifiation of trmEval */ #else typedef long num; # define NUM_MIN LONG_MIN # define NUM_MAX LONG_MAX #endif static int debug_g = 0; static int (*user_parse_g)(mcxTing* txt, int offset) = NULL; static mcxenum (*user_eval_g)(const char* token, long *ival, double *fval) = NULL; static char user_char_g = 0; typedef struct tn /* the lex/parse/interpret one stop-shop */ { mcxTing* token ; i32 toktype ; i32 optype ; i32 opid ; real fval ; num ival ; struct tn* prev ; struct tn* next ; i32 flags ; } tn; /* token node, or whatever */ struct telRaam { mcxTing *text ; mcxTing *token /* current token */ ; char* p ; mcxbool buffered /* should use buffer (pushed back token)? */ ; tn* node ; tn* start ; real fval ; num ival ; i32 flags ; i32 toktype ; i32 depth ; } ; typedef enum { TOKEN_EXH = -1 , TOKEN_START = 0 /* special start symbol */ , TOKEN_UNIOP = 1 /* unary, 1 */ , TOKEN_BINOP = 2 /* binary, 2 */ , TOKEN_FUN = 69 /* can be fun, but I mean 6 = ( 9 = ) */ , TOKEN_TRIOP = 3333 /* ternary, let's stress the fact */ , TOKEN_TRICATCH = 6667 /* complement of a number wrt another number */ , TOKEN_CMP = 12321 /* hum, dunnow really */ , TOKEN_OR = 11 /* || */ , TOKEN_AND = 88 /* && */ , TOKEN_OPEN = 6 /* like fun, 6 = ( */ , TOKEN_CLOSE = 9 /* like fun, 9 = ) */ , TOKEN_COMMA = 13579 /* gaps */ , TOKEN_CONST = 31415 /* PI */ , TOKEN_USER = 981 /* G, variable */ } tokentype ; #define OP_UNI_NEG 1 << 0 /* - */ #define OP_UNI_NOT 1 << 1 /* ! */ #define OP_UNI_COMPL 1 << 2 /* ~ */ #define OP_EXP_EXP 1 << 3 /* ** */ #define OP_MUL_MUL 1 << 4 /* * */ #define OP_MUL_FRAC 1 << 5 /* / */ #define OP_MUL_DIV 1 << 6 /* // */ #define OP_MUL_MOD 1 << 7 /* % */ #define OP_ADD_ADD 1 << 8 /* + */ #define OP_ADD_SUB 1 << 9 /* - */ #define OP_BIT_LSHIFT 1 << 10 /* << */ #define OP_BIT_RSHIFT 1 << 11 /* >> */ #define OP_BIT_AND 1 << 12 /* & */ #define OP_BIT_OR 1 << 13 /* | */ #define OP_BIT_XOR 1 << 14 /* ^ */ #define OP_CMP_LT 1 << 15 /* < */ #define OP_CMP_LQ 1 << 16 /* <= */ #define OP_CMP_GQ 1 << 17 /* >= */ #define OP_CMP_GT 1 << 18 /* > */ #define OP_CMP_EQ 1 << 19 /* == */ #define OP_CMP_NE 1 << 20 /* != */ #define OP_TRI_START 1 << 21 /* ! */ #define OPTYPE_UNI (OP_UNI_NEG | OP_UNI_NOT | OP_UNI_COMPL) #define OPTYPE_EXP OP_EXP_EXP #define OPTYPE_MUL (OP_MUL_MUL | OP_MUL_FRAC | OP_MUL_DIV | OP_MUL_MOD) #define OPTYPE_ADD (OP_ADD_ADD | OP_ADD_SUB) #define OPTYPE_BIT (OP_BIT_LSHIFT | OP_BIT_RSHIFT \ | OP_BIT_AND | OP_BIT_OR | OP_BIT_XOR) #define OPTYPE_CMP (OP_CMP_LT | OP_CMP_LQ | OP_CMP_GT | OP_CMP_GQ \ | OP_CMP_EQ | OP_CMP_NE) #define OPTYPE_TRI OP_TRI_START typedef struct opHook { char* opname ; i32 opid ; i32 optype ; } opHook ; double sign (double f ) { return f > 0 ? 1.0 : f < 0 ? -1.0 : 0.0 ; } double letround (double f ) { return f > 0 ? floor(f+0.5) : ceil(f-0.5) ; } double letlog2 (double f) { return f > 0 ? log(f) / log(2.0) : 0.0 ; } typedef struct fun1Hook { char* funname ; double (*funcd)(double a) ; i32 funflags ; } fun1Hook ; #define FUN_SPECIAL 1 #define FUN_INTRESULT 2 #define FUN_OVERLOADED 4 double show_bits(double a) { return a; } static fun1Hook fun1HookDir[] = { { "sin", sin , 0 } , { "cos", cos , 0 } , { "tan", tan , 0 } , { "exp", exp , 0 } , { "log", log , 0 } , { "log10", log10 , 0 } , { "log2", letlog2 , 0 } , { "asin", asin , 0 } , { "acos", cos , 0 } , { "atan", atan , 0 } , { "sqrt", sqrt , 0 } , { "abs", fabs , FUN_SPECIAL } , { "floor", floor , FUN_INTRESULT } , { "ceil", ceil , FUN_INTRESULT } , { "round", letround , FUN_INTRESULT } , { "int", letround , FUN_INTRESULT } , { "sign", sign , FUN_INTRESULT } , { "bits", show_bits , FUN_SPECIAL } , { NULL, NULL , 0 } } ; double max ( double a, double b ) { return a > b ? a : b ; } double min ( double a, double b ) { return a < b ? a : b ; } num maxl ( num a, num b ) { return a > b ? a : b ; } num minl ( num a, num b ) { return a < b ? a : b ; } typedef struct fun2Hook { char* funname ; double (*funcd)(double a, double b) ; num (*funcl)(num a, num b) ; i32 funflags ; } fun2Hook ; static fun2Hook fun2HookDir[] = { { "max", max , maxl, 0 } , { "min", min , minl, 0 } , { NULL, NULL , NULL, 0 } } ; /* mq if (tn_isint(lft) && tn_isint(rgt) && hook->funcl) */ static opHook opHookDir[] = { { "-", OP_UNI_NEG, OPTYPE_UNI } , { "!", OP_UNI_NOT, OPTYPE_UNI } , { "~", OP_UNI_COMPL, OPTYPE_UNI } , { "**", OP_EXP_EXP, OPTYPE_EXP } , { "*", OP_MUL_MUL, OPTYPE_MUL } , { "/", OP_MUL_FRAC, OPTYPE_MUL } , { "//", OP_MUL_DIV, OPTYPE_MUL } , { "%", OP_MUL_MOD, OPTYPE_MUL } , { "+", OP_ADD_ADD, OPTYPE_ADD } , { "-", OP_ADD_SUB, OPTYPE_ADD } , { "<<", OP_BIT_LSHIFT, OPTYPE_BIT } , { ">>", OP_BIT_RSHIFT, OPTYPE_BIT } , { "&", OP_BIT_AND, OPTYPE_BIT } , { "|", OP_BIT_OR, OPTYPE_BIT } , { "^", OP_BIT_XOR, OPTYPE_BIT } , { "<", OP_CMP_LT, OPTYPE_CMP } , { "<=", OP_CMP_LQ, OPTYPE_CMP } , { ">=", OP_CMP_GQ, OPTYPE_CMP } , { ">", OP_CMP_GT, OPTYPE_CMP } , { "==", OP_CMP_EQ, OPTYPE_CMP } , { "!=", OP_CMP_NE, OPTYPE_CMP } , { "?", OP_TRI_START, OPTYPE_TRI } , { NULL, 0, 0, } } ; enum { EXPECT_ANY = 1 , EXPECT_ATOM = 2 } ; #define TN_ISINT 1 /* tn token node, object used everywhere */ #define TN_NOINT 2 #define TN_ISNAN 4 #define TN_ISINF 8 #define tn_isint(a) (a->flags & TN_ISINT) mcxbool trmIsNan ( int flags ) { return flags & TN_ISNAN ; } mcxbool trmError ( int flags ) { return flags & (TN_ISNAN | TN_ISINF) ; } mcxbool trmIsInf ( int flags ) { return flags & TN_ISINF ; } mcxbool trmIsNum ( int flags ) { return flags & TN_ISINT ; } mcxbool trmIsReal ( int flags ) { return !(flags & (TN_ISINT | TN_ISNAN | TN_ISINF)) ; } mcxstatus getexpression ( telRaam *raam ) ; mcxstatus getatom ( telRaam* raam ) ; void dump ( tn* node , i32 times , const char* msg ) ; void trmDump ( telRaam* raam , const char* msg ) { dump(raam->start, 0, msg) ; } tn* tnNewToken ( const char* token , i32 toktype , real fval , num ival ) { tn* node = mcxAlloc(sizeof(tn), RETURN_ON_FAIL) ; if (!node) return NULL ; if (!(node->token = mcxTingNew(token ? token : "_<>_"))) { mcxFree(node) ; return NULL ; } node->toktype = toktype ; node->optype = 0 ; node->opid = 0 ; node->ival = ival ; node->fval = fval ; node->next = NULL ; node->prev = NULL ; node->flags = 0 ; if (debug_g) dump(node, 1, "new node") ; return node ; } tn* tnDup ( tn* this , const char* str ) { tn* new = tnNewToken ( str , this->toktype , this->fval , this->ival ) ; if (!new) return NULL ; new->optype = this->optype ; new->next = this->next ; new->prev = this->prev ; new->flags = this->flags ; return new ; } mcxstatus tnFree ( tn* lft , tn* rgt ) { tn* cur = lft, *next ; while (cur) { mcxTingFree(&(cur->token)) ; if (debug_g) fprintf(stderr, "___ [telraam] freeing node <%p>\n", (void*) cur) ; if (cur == rgt) { mcxFree(cur) ; break ; } if (cur->next && cur->next->prev != cur) { mcxErr("tnFree", "free encountered spaghetti") ; return STATUS_FAIL ; } next = cur->next ; mcxFree(cur) ; cur = next ; } return STATUS_OK ; } void tnLink2 ( tn* one , tn* two ) { if (one) one->next = two ; if (two) two->prev = one ; } void tnLink3 ( tn* one , tn* two , tn* three ) { if (one) one->next = two ; if (three) three->prev = two ; two->prev = one ; two->next = three ; } mcxstatus tnPushToken ( telRaam* raam ) { i32 toktype = raam->toktype ; tn* new = tnNewToken(raam->token->str, toktype, 0.0, 0) ; if (!new) return STATUS_FAIL ; if (toktype == TOKEN_CONST) new->fval = raam->fval , new->ival = raam->ival , new->flags = raam->flags ; else if ( toktype == TOKEN_BINOP || toktype == TOKEN_UNIOP ) { opHook* oh = raam->toktype == TOKEN_BINOP ? opHookDir+3 : opHookDir+0 /* bigg phat ugly hack */ /* (need to overcome '-' uni/bin ambiguity */ ; while (oh->opname) { if (!strcmp(oh->opname, raam->token->str)) { new->optype = oh->optype ; new->opid = oh->opid ; break ; } oh++ ; } if (!oh->opname) { mcxErr("tnPushToken", "no such operator: <%s>", raam->token->str) ; tnFree(new, NULL) ; return STATUS_FAIL ; } } else if (raam->toktype == TOKEN_FUN) { /* mq: move name resolution to here ? mm, needs arity */ ; } tnLink3(raam->node, new, NULL) ; raam->node = new ; return STATUS_OK ; } mcxstatus tnPushThis ( telRaam* raam , const char* token , i32 toktype ) { tn* new = tnNewToken(token, toktype, 0.0, 0) ; if (!new) return STATUS_FAIL ; tnLink3(raam->node, new, NULL) ; raam->node = new ; return STATUS_OK ; } void trmDebug ( void ) { debug_g = 1 ; } telRaam* trmInit ( const char* str ) { telRaam* raam= mcxAlloc(sizeof(telRaam), RETURN_ON_FAIL) ; if (!raam) return NULL ; raam->text = mcxTingNew(str) ; raam->token = mcxTingEmpty(NULL, 30) ; raam->p = raam->text->str ; raam->buffered = FALSE ; raam->node = tnNewToken("_start_", TOKEN_START, 0.0, 0) ; raam->start = raam->node ; raam->fval = 0.0 ; raam->ival = 0 ; raam->flags = 0 ; raam->depth = 1 ; raam->toktype= 0 ; if (!raam->text || !raam->token || !raam->node) mcxFree(raam) , raam = NULL ; return raam ; } mcxstatus trmExit ( telRaam* raam ) { if (tnFree(raam->start, raam->node)) return STATUS_FAIL ; mcxTingFree(&(raam->text)) ; mcxTingFree(&(raam->token)) ; mcxFree(raam) ; return STATUS_OK ; } void untoken ( telRaam* raam ) { raam->buffered = TRUE ; } void dump ( tn* node , i32 times , const char* msg ) { tn* prev = NULL ; printf("______ %s\n", msg ? msg : "dumping dumping dumping") ; printf ("%8s" "%10s" "%10s" "%10s" "%12s" "%10s" "%6s\n" ,"toktype","optype","opclass","token","fval","ival","flags" ) ; while (node) { printf ("%8d" "%10d" "%10d" "%10s" "%12.4f""%10ld""%6d\n" , node->toktype , node->opid , node->optype , node->token ? node->token->str : "<>" , node->fval , (long) node->ival , node->flags ) ; prev = node ; node = node->next ; if (node && (node->prev->next != node || node->prev != prev)) fprintf ( stderr , "_____ [telraam] PANICK incorrect linking" " <%p> n<%p> np<%p> npn<%p>\n" , (void*) prev , (void*) node , (void*) node->prev , (void*) node->prev->next ) ; if (!--times) break ; } } int getatoken ( telRaam* raam , i32 mode ) { char* p = raam->p ; i32 toktype = 0 ; int len ; while (isspace((unsigned char) *p)) p++ ; raam->p = p ; if (!*p) { mcxTingWrite(raam->token, "EOF") ; return TOKEN_EXH ; } else if ( mode == EXPECT_ATOM && ( *p == '-' || *p == '!' || *p == '~' ) ) { toktype = TOKEN_UNIOP ; p = p+1 ; } else if (*p == ':') { toktype = TOKEN_TRICATCH ; p = p+1 ; } else if (*p == '&' && *(p+1) == '&') { toktype = TOKEN_AND ; p = p+2 ; } else if (*p == '|' && *(p+1) == '|') { toktype = TOKEN_OR ; p = p+2 ; } else if (*p == '?') { toktype = TOKEN_TRIOP ; p = p+1 ; } else if (*p == ',') { toktype = TOKEN_COMMA ; p = p+1 ; } else if (isdigit((unsigned char) *p)) { int l ; double f ; sscanf(p, "%lf%n", &f, &l) /* mq need error checking */ ; toktype = TOKEN_CONST ; raam->fval = f ; raam->ival = 0 ; if (raam->fval < NUM_MIN || raam->fval > NUM_MAX) raam->flags = TN_NOINT ; else { raam->flags = mcxStrChrAint(p, isdigit, l) ? 0 : TN_ISINT ; raam->ival = f > 0 ? f + 0.5 : f - 0.5 ; } p = p+l ; } else if (isalpha((unsigned char) *p) || *p == '_') { char* q = p ; while(isalpha((unsigned char) *q) || *q == '_' || isdigit((unsigned char) *q)) q++ ; p = q ; toktype = TOKEN_FUN ; } else if (*p == '(' || *p == ')') { toktype = *p == '(' ? TOKEN_OPEN : TOKEN_CLOSE ; p = p+1 ; } else if ( user_char_g == *p && (len = user_parse_g(raam->text, p-raam->text->str)) > 0 ) /* ^truncintok */ { p += len ; toktype = TOKEN_USER ; } else { char* q = p ; while (*q == *p || *q == '=') /* hack */ q++ ; toktype = TOKEN_BINOP ; p = q ; } mcxTingNWrite(raam->token, raam->p, (dim) (p-raam->p)) ; raam->p = p ; return toktype ; } i32 gettoken ( telRaam* raam , i32 mode ) { if (raam->buffered) raam->buffered = FALSE ; else raam->toktype = getatoken(raam, mode) ; return raam->toktype ; } tn* findop ( tn* end ) { tn* node = end->prev, *max = NULL ; while (node->toktype != TOKEN_OPEN) { if ( node->toktype == TOKEN_UNIOP || node->toktype == TOKEN_BINOP || node->toktype == TOKEN_TRIOP ) { if ( !max || node->optype <= max->optype ) max = node ; } node = node->prev ; } return max ; } tn* finduser ( tn* start ) { tn* node = start->next ; while (node->toktype != TOKEN_CLOSE) { if (node->toktype == TOKEN_USER) return node ; node = node->next ; } return NULL ; } mcxstatus tnUser ( tn* usr ) { mcxenum stat = user_eval_g(usr->token->str, &usr->ival, &usr->fval) ; if (stat == TRM_ISNUM) { usr->flags = TN_ISINT ; usr->fval = usr->ival ; } else if (stat == TRM_ISREAL) usr->flags = 0 ; else if (stat == TRM_ISNAN) { usr->flags = TN_ISNAN ; return STATUS_FAIL ; } else if (stat == TRM_FAIL) { usr->flags = TN_ISNAN ; return STATUS_FAIL ; } usr->toktype = TOKEN_CONST ; return STATUS_OK ; } /* * Flattens a bunch of leafs interspersed with operators. * Leaves received start and corresponding end alone. */ mcxstatus flatten ( tn* start , tn* end ) { tn* new, *op, *usr ; real fval = 0.0 ; num ival = 0 ; const char* me = "flatten" ; if ( start->toktype != TOKEN_OPEN || end->toktype != TOKEN_CLOSE ) { mcxErr ( me , "wrong toktype - ids (%p, %p)" , (void*) start, (void*) end ) ; dump(start, 0, NULL) ; return STATUS_FAIL ; } new = start->next ; while ((usr = finduser(start))) { if (tnUser(usr)) return STATUS_FAIL ; } while ((op = findop(end))) { tn* lft = op->prev ; tn* rgt = op->next /* ugly in case of UNIOP */ ; int err = 0 ; i32 flags = 0 ; if (op->toktype == TOKEN_UNIOP) { real frgt = rgt->fval ; num irgt = rgt->ival ; switch(op->opid) { case OP_UNI_NOT : ival = (tn_isint(rgt) && irgt) ? 0 : frgt ? 0 : 1 ; fval = ival ; flags |= TN_ISINT ; break ; case OP_UNI_NEG : fval = -frgt ; ival = -irgt ; break ; case OP_UNI_COMPL : ival = ~irgt ; fval = ival ; flags |= TN_ISINT ; break ; default : err = 1 ; } lft = op ; flags |= tn_isint(rgt) /* mq fval=ival assignment ugly, need overflow check as well :) */ ; } else if (op->toktype == TOKEN_BINOP) { real flft = lft->fval ; real frgt = rgt->fval ; num ilft = lft->ival ; num irgt = rgt->ival ; if (op->opid & OPTYPE_BIT) { if (!tn_isint(lft)) ilft = lft->fval /* fixme: why the reassign? */ ; if (!tn_isint(rgt)) irgt = rgt->fval /* fixme: why the reassign? */ ; if (!tn_isint(rgt) || !tn_isint(lft)) mcxErr ( "let" , "[flatten][bitop %s] forcing real operands to number" , op->token->str ) ; } if (lft->toktype != TOKEN_CONST || rgt->toktype != TOKEN_CONST) { mcxErr(me, "this bifoo is not the right foo") ; dump(start, 0, NULL) ; return STATUS_FAIL ; } switch(op->opid) { case OP_MUL_MUL : fval = flft * frgt ; ival = ilft * irgt ; break ; case OP_EXP_EXP : if (flft < 0 && !(rgt->flags & TN_ISINT)) fval = 0.0 , flags |= TN_ISNAN ; else fval = pow(flft,frgt) ; ival = letround(fval) ; break ; case OP_ADD_ADD : fval = flft + frgt ; ival = ilft + irgt ; break ; case OP_MUL_FRAC : fval = frgt ? (flft / frgt) : 0.0 ; ival = irgt ? (ilft / irgt) : 0 ; if (tn_isint(lft) && tn_isint(rgt) && ival * irgt == ilft) flags |= TN_ISINT ; else flags |= TN_NOINT ; if (!frgt) flags |= TN_ISNAN ; break ; case OP_MUL_DIV : fval = frgt ? floor(flft/frgt) : 0.0 ; ival = irgt ? (ilft / irgt) : 0 ; if (!frgt) flags |= TN_ISNAN ; break ; case OP_MUL_MOD : fval = frgt ? frgt * (flft/frgt-floor(flft/frgt)) : 0.0 ; ival = irgt ? (ilft % irgt) : 0.0 ; if (!frgt) flags |= TN_ISNAN ; break ; case OP_ADD_SUB : fval = flft - frgt ; ival = ilft - irgt ; break ; case OP_CMP_LT : ival = tn_isint(lft) && tn_isint(rgt) && (ilft < irgt) ? 1 : flft < frgt ? 1 : 0 ; flags |= TN_ISINT ; break ; case OP_CMP_LQ : ival = tn_isint(lft) && tn_isint(rgt) && (ilft <= irgt) ? 1 : flft <= frgt ? 1 : 0 ; flags |= TN_ISINT ; break ; case OP_CMP_GQ : ival = tn_isint(lft) && tn_isint(rgt) && (ilft >= irgt) ? 1 : flft >= frgt ? 1 : 0 ; flags |= TN_ISINT ; break ; case OP_CMP_GT : ival = tn_isint(lft) && tn_isint(rgt) && (ilft > irgt) ? 1 : flft > frgt ? 1 : 0 ; flags |= TN_ISINT ; break ; case OP_CMP_EQ : ival = tn_isint(lft) && tn_isint(rgt) && (ilft == irgt) ? 1 : flft == frgt ? 1 : 0 ; flags |= TN_ISINT ; break ; case OP_CMP_NE : ival = tn_isint(lft) && tn_isint(rgt) && (ilft != irgt) ? 1 : flft != frgt ? 1 : 0 ; flags |= TN_ISINT ; break ; case OP_BIT_LSHIFT : ival = ilft << irgt ; flags |= TN_ISINT ; break ; case OP_BIT_RSHIFT : ival = ilft >> irgt ; flags |= TN_ISINT ; break ; case OP_BIT_AND : ival = ilft & irgt ; flags |= TN_ISINT ; break ; case OP_BIT_OR : ival = ilft | irgt ; flags |= TN_ISINT ; break ; case OP_BIT_XOR : ival = ilft ^ irgt ; flags |= TN_ISINT ; break ; default : err = 1 ; } /* this rule implements implicit behaviour with overruling: * two integers result in an integer unless overruled * with the TN_NOINT attribute. */ if (!(flags & TN_NOINT)) flags |= tn_isint(lft) & tn_isint(rgt) /* next we check whether overflow occurred. If so, discard the * integer attribute. This depends on i) fval follows ival as * long as the integer attribute is set and ii) in that pursuit, * fval is computed to be similar to ival. */ ; if ((fval > NUM_MAX || fval < NUM_MIN) && (flags & TN_ISINT)) flags ^= TN_ISINT /* make fval follow ival, otherwise, give ival special * value. *Never* should float->int conversion happen * in this code; it should be user-enforced. * Setting ival to 0 may help show any such behaviour as a bug. */ ; if (flags & TN_ISINT) fval = ival ; else ival = 0 ; } else { mcxErr(me, "panicking at toktype <%ld>", (long) op->toktype) ; return STATUS_FAIL ; } if (err) { mcxErr ( me , "op <%s> id <%ld> class <%ld> not yet supported" , op->token->str , (long) op->opid , (long) op->optype ) ; return STATUS_FAIL ; } if (flags & TN_ISNAN) { mcxErr(me, "arithmetic exception for op <%s>", op->token->str) ; return STATUS_FAIL ; } if (!(new = tnNewToken("_eval_", TOKEN_CONST, fval, ival))) return STATUS_FAIL ; new->flags = flags /* mq need overflow check, nan check etc */ ; tnLink3(lft->prev, new, rgt->next) ; if (tnFree(lft, rgt)) return STATUS_FAIL ; } return STATUS_OK ; } fun1Hook* getfun1id ( tn* start ) { fun1Hook *fh = fun1HookDir+0 ; while (fh->funname && strcmp(fh->funname, start->token->str)) fh++ ; return fh->funname ? fh : NULL ; } fun2Hook* getfun2id ( tn* start ) { fun2Hook *fh = fun2HookDir+0 ; while (fh->funname && strcmp(fh->funname, start->token->str)) fh++ ; return fh->funname ? fh : NULL ; } tn* funcx ( tn* start , tn* end ) { tn *new, *arg = end->prev ; real fval = 0.0 ; num ival = 0 ; i32 flags = 0 ; int n_args = arg->toktype == TOKEN_CONST ; int err = 0 ; const char* me = "funcx" ; const char* fn = "_init_" ; if ( start->toktype != TOKEN_FUN || start->next->toktype != TOKEN_OPEN || end->toktype != TOKEN_CLOSE ) { mcxErr(me, "wrong toktype - ids (%p, %p)", (void*) start, (void*) end) ; dump(start, 0, NULL) ; return NULL ; } while ( arg->toktype == TOKEN_CONST && arg->prev->toktype == TOKEN_COMMA ) arg = arg->prev->prev , n_args++ ; if (arg->prev != start->next) { mcxErr(me, "this function foo is not the right foo") ; dump(start, 0, NULL) ; return NULL ; } if (n_args == 1) { tn* op1 = arg ; fun1Hook* fh = getfun1id(start) ; if (fh) { fn = fh->funname ; if (fh->funflags & FUN_SPECIAL) { if (!strcmp(fn, "abs")) { if (tn_isint(op1)) { ival = op1->ival > 0 ? op1->ival : -op1->ival ; flags |= TN_ISINT ; } else fval = op1->fval > 0 ? op1->fval : -op1->fval ; } else if (!strcmp(fn, "bits")) { if (tn_isint(op1)) { ival = op1->ival ; flags |= TN_ISINT /* mq show the damn bits */ ; } else fval = op1->fval /* mq show the damn bits */ ; } else err = 1 ; } else { fval = (fh->funcd)(op1->fval) ; if ( fh->funflags & FUN_INTRESULT && fval <= NUM_MAX && fval >= NUM_MIN ) { flags |= TN_ISINT ; ival = (num) fval > 0 ? fval+0.5 : fval - 0.5 ; } } } else err = 1 ; } else if (n_args == 2) { tn* op1 = arg, *op2 = op1->next->next ; fun2Hook* fh = getfun2id(start) ; if (fh) { fn = fh->funname ; if (tn_isint(op1) && tn_isint(op2) && fh->funcl) { ival = (fh->funcl)(op1->ival, op2->ival) ; flags |= TN_ISINT ; } else fval = (fh->funcd)(op1->fval, op2->fval) ; } else err = 1 ; } else err = 1 ; if (err) { mcxErr ( me , "<%s> [%d] not supported" , start->token->str , n_args ) ; return NULL ; } else { if (!(new = tnNewToken(fn, TOKEN_CONST, fval, ival))) return NULL ; new->flags = flags ; } return new ; } tn* match ( tn* start ) { int depth = 1 ; if (start->toktype != TOKEN_OPEN) { mcxErr("match", "node <%p> has wrong toktype", (void*) start) ; return NULL ; } while (start->next) { start = start->next ; if (start->toktype == TOKEN_OPEN) depth++ ; else if (start->toktype == TOKEN_CLOSE) { depth-- ; if (!depth) break ; } } return depth ? NULL : start ; } /* * must leave received start and corresponding end alone */ mcxstatus compute ( tn* start ) { tn* ptr, *new, *end ; const char* me = "compute" ; if (start->toktype != TOKEN_OPEN) { mcxErr(me, "node <%p> has wrong toktype", (void*) start) ; return(STATUS_FAIL) ; } if (!(end = match(start))) { mcxErr(me, "node <%p> has no match", (void*) start) ; return(STATUS_FAIL) ; } ptr = start->next ; while (ptr) /* ok by the naming police? */ { tn* eosc, *val ; if (ptr->toktype == TOKEN_FUN) { if (compute(ptr->next)) return STATUS_FAIL /* now:: LPT op CM [op CM]* RPT */ ; eosc = match(ptr->next) ; if (!eosc || !(val = funcx(ptr, eosc))) return STATUS_FAIL /* now:: fun LPT val RPT */ ; tnLink3(ptr->prev, val, eosc->next) ; if (tnFree(ptr, eosc)) return STATUS_FAIL ; ptr = val->next ; } else if (ptr->toktype == TOKEN_OPEN) { if (compute(ptr)) return STATUS_FAIL ; if (!(eosc = match(ptr))) /* should check singularity */ return STATUS_FAIL ; if (!(val = tnDup(eosc->prev, "_scope_"))) return STATUS_FAIL ; tnLink3(ptr->prev, val, eosc->next) ; if (tnFree(ptr, eosc)) return STATUS_FAIL ; ptr = val->next ; } /* should check presence TRICATCH */ else if (ptr->toktype == TOKEN_TRIOP) { tn* br1 = ptr->next, *br2, *eobr1, *eobr2 /* branches */ ; if (!(eobr1 = match(br1))) return STATUS_FAIL ; if (!(br2 = eobr1->next->next)) return STATUS_FAIL ; eobr2 = match(br2) ; if (ptr->prev->fval) /* mqmq! logic by fval */ { if (compute(br1)) return STATUS_FAIL ; if (!(new = tnDup(br1->next, "triop1"))) return STATUS_FAIL ; tnLink3(ptr->prev->prev, new, eobr2->next) ; if (tnFree(ptr->prev, eobr2)) return STATUS_FAIL ; } else { if (compute(br2)) return STATUS_FAIL ; if (!(new = tnDup(br2->next, "triop2"))) return STATUS_FAIL ; tnLink3(ptr->prev->prev, new, eobr2->next) ; if (tnFree(ptr->prev, eobr2)) return STATUS_FAIL ; } ptr = new->next ; } else if (ptr->toktype == TOKEN_AND) /* now:: val AND LPT any RPT */ { tn* pivot = ptr->prev, *clause=ptr->next, *after ; if (pivot->fval) { if (compute(clause)) return STATUS_FAIL /* should check singularity of result */ /* lpt val rpt ? */ ; after = clause->next->next->next /* oops, ugly dugly */ ; pivot->fval = clause->next->fval /* mqmq! logic by fval */ ; if (tnFree(pivot->next, after->prev)) return STATUS_FAIL ; tnLink2(pivot, after) ; ptr = after ; } else { tn* eoclause = match(clause) ; tn* any = eoclause ? eoclause->next : NULL ; if (!eoclause || tnFree(pivot->next, eoclause)) return STATUS_FAIL ; tnLink2(pivot, any) ; ptr = any ; } pivot->ival = pivot->fval ? 1 : 0 ; pivot->flags |= TN_ISINT ; } else if (ptr->toktype == TOKEN_OR) { tn* pivot = ptr->prev, *clause=ptr->next, *after ; if (pivot->fval) { tn* eoclause = match(clause) ; tn* any = eoclause ? eoclause->next : NULL ; if (!eoclause || tnFree(pivot->next, eoclause)) return STATUS_FAIL ; tnLink2(pivot, any) ; ptr = any ; } else { if (compute(clause)) return STATUS_FAIL /* should check singularity of result */ ; after = clause->next->next->next /* oops, ugly dugly */ ; pivot->fval = clause->next->fval /* mqmq! logic by fval */ ; if (tnFree(pivot->next, after->prev)) return STATUS_FAIL ; tnLink2(pivot, after) ; ptr = after ; } pivot->ival = pivot->fval ? 1 : 0 ; pivot->flags |= TN_ISINT ; } else if (ptr->toktype == TOKEN_CLOSE) break ; else ptr = ptr->next ; } /* NOTE: by design we should always have ptr != NULL * that makes the clause to the while (ptr) { } loop * above a bit dodgy. */ if (ptr != end || ptr->toktype != TOKEN_CLOSE) { mcxErr(me, "ptr does not close") ; dump(ptr->prev, 0, NULL) ; return STATUS_FAIL ; } if (flatten(start, ptr)) return STATUS_FAIL ; return STATUS_OK ; } mcxstatus getatom ( telRaam* raam ) { i32 toktype = gettoken(raam, EXPECT_ATOM) ; const char* me = "getatom" ; if (toktype < 0) { mcxErr(me, "unexpected token <%s>", raam->token->str) ; return STATUS_FAIL ; } ; if (toktype == TOKEN_UNIOP) { if (tnPushToken(raam)) return STATUS_FAIL ; if (getatom(raam)) return STATUS_FAIL ; } else if (toktype == TOKEN_OPEN) { if (getexpression(raam)) return STATUS_FAIL ; if ((toktype = gettoken(raam, EXPECT_ANY)) != TOKEN_CLOSE) { mcxErr(me, "no close (token <%ld>)", (long) toktype) ; return STATUS_FAIL ; } if (raam->depth < 0) { mcxErr(me, "spurious rpth (atom I)") ; return STATUS_FAIL ; } } else if (toktype == TOKEN_FUN) { if (tnPushToken(raam)) return STATUS_FAIL ; if (tnPushThis(raam, "_open_", TOKEN_OPEN)) return STATUS_FAIL ; if ((toktype = gettoken(raam, EXPECT_ANY)) != TOKEN_OPEN) { mcxErr(me, "expect '(' after function symbol") ; return STATUS_FAIL ; } while(1) { if (getexpression(raam)) return STATUS_FAIL ; if (gettoken(raam, EXPECT_ANY) == TOKEN_COMMA) { if (tnPushToken(raam)) return STATUS_FAIL ; } else { untoken(raam) ; break ; } } if ((toktype = gettoken(raam, EXPECT_ANY)) != TOKEN_CLOSE) { mcxErr(me, "expect ')' closing function symbol") ; return STATUS_FAIL ; } if (tnPushThis(raam, "_close_", TOKEN_CLOSE)) return STATUS_FAIL ; } else if (toktype == TOKEN_CONST) { if (tnPushToken(raam)) return STATUS_FAIL ; } else if (toktype == TOKEN_CLOSE) { mcxErr(me, "empty group not allowed") ; return STATUS_FAIL ; } else if (toktype == TOKEN_USER) { if (tnPushToken(raam)) return STATUS_FAIL ; } else { mcxErr(me, "unexpected token <%s> (atom)", raam->token->str) ; return STATUS_FAIL ; } return STATUS_OK ; } mcxstatus getexpression ( telRaam* raam ) { i32 toktype ; const char* me = "getexpression" ; raam->depth++ ; if (tnPushThis(raam, "_open_", TOKEN_OPEN)) return STATUS_FAIL ; while (1) { if (getatom(raam)) return STATUS_FAIL ; toktype = gettoken(raam, EXPECT_ANY) ; if (toktype == TOKEN_BINOP) { if (tnPushToken(raam)) return STATUS_FAIL ; } else if (toktype == TOKEN_AND) { if (tnPushThis(raam, "_close_", TOKEN_CLOSE)) return STATUS_FAIL ; if (tnPushToken(raam)) return STATUS_FAIL ; if (tnPushThis(raam, "_open_", TOKEN_OPEN)) return STATUS_FAIL ; } else if (toktype == TOKEN_OR) { if (tnPushThis(raam, "_close_", TOKEN_CLOSE)) return STATUS_FAIL ; if (tnPushToken(raam)) return STATUS_FAIL ; if (tnPushThis(raam, "_open_", TOKEN_OPEN)) return STATUS_FAIL ; } else if (toktype == TOKEN_TRIOP) { if (tnPushThis(raam, "_close_", TOKEN_CLOSE)) return STATUS_FAIL ; if (tnPushToken(raam)) return STATUS_FAIL ; if (tnPushThis(raam, "_open_", TOKEN_OPEN)) return STATUS_FAIL ; if (getexpression(raam)) return STATUS_FAIL ; if (tnPushThis(raam, "_close_", TOKEN_CLOSE)) return STATUS_FAIL ; toktype = gettoken(raam, EXPECT_ANY) ; if (toktype != TOKEN_TRICATCH) { mcxErr ( me , "unexpected token <%s> (expression)" , raam->token->str ) ; return STATUS_FAIL ; } if (tnPushToken(raam)) return STATUS_FAIL ; if (tnPushThis(raam, "_open_", TOKEN_OPEN)) return STATUS_FAIL ; } else if ( toktype == TOKEN_COMMA || toktype == TOKEN_CLOSE || toktype == TOKEN_EXH || toktype == TOKEN_TRICATCH ) { untoken(raam) ; break ; } else { mcxErr ( me , "unexpected token <%s> <%ld> (expression)" , raam->token->str , (long) toktype ) ; return STATUS_FAIL ; } } if (tnPushThis(raam, "_close_", TOKEN_CLOSE)) return STATUS_FAIL ; raam->depth-- ; return STATUS_OK ; } mcxstatus trmParse ( telRaam* raam ) { if (tnPushThis(raam, "_open_", TOKEN_OPEN)) return STATUS_FAIL ; if (getexpression(raam)) return STATUS_FAIL ; if (tnPushThis(raam, "_close_", TOKEN_CLOSE)) return STATUS_FAIL ; if (gettoken(raam, EXPECT_ANY) != TOKEN_EXH) { mcxErr("trmParse", "spurious token <%s>", raam->token->str) ; return STATUS_FAIL ; } return STATUS_OK ; } void trmRegister ( telRaam* raam cpl__unused , int (user_parse)(mcxTing* txt, int offset) , mcxenum (user_eval)(const char* token, long *ival, double *fval) , char user_char ) { user_parse_g = user_parse ; user_eval_g = user_eval ; user_char_g = user_char ; } int trmEval ( telRaam* raam , long* lp , double* fp ) { tn* result ; mcxstatus stat = compute(raam->start->next) ; result = stat ? NULL : (raam->start->next->next) ; if (result) { *lp = result->ival ; *fp = result->fval ; return result->flags ; } return -1 ; } zoem-11-166/util/list.c0000644000402500021140000001106511147246067011602 00000000000000/* (C) Copyright 2004, 2005, 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #include "list.h" #include "alloc.h" #include "gralloc.h" #include "compile.h" #define DEBUG 0 /* TODO. very funny interface. in flux. * * ! allow null argument for linkdelete. * * ! * little support for corruption checking. * is the spawn thing a good idea ? * ! * interface with list object, or not? * not requires hidden list pointer everywhere (have that now). * perhaps supply separate interface with list handle .. ?] * ! * how to unify FLink, BLink, and link (forward/backward/bidi) * optify hidden list pointer, next xor prev pointer. * * - Add triple sanity checks for user supplied data (?) * - implement val freeing. * - with deleting, should warn if no handle remains .. * and can check grim count. */ /* Note. * We very much do not want to define (as previously thought) next and prev * as const pointers (with the goal of keeping chain consistency up * to this interface). * This interface provides some convenience interfaces, but * the integrity and life-cycle of the chains built with the links * is entirely up to the caller. So tie-rap away with them links. * * So we do not keep track of list characteristics, * e.g. first, last, count. That would be something for a higher layer. */ typedef struct { mcxGrim* grim ; } mcx_list ; typedef struct lsptr { mcx_list* ls ; } lsptr ; #define mcx_list_find(lk) ((lsptr*)((void*)((char*) lk - sizeof(lsptr))))->ls void mcx_link_init ( mcxLink* lk , void* val ) { lk->next = NULL ; lk->prev = NULL ; lk->val = val ; } mcxLink* mcx_list_shift ( mcx_list* ls , void* val ) { void* mem ; mcxLink* lk ; if (!(mem = mcxGrimGet(ls->grim))) return NULL ; lk = (void*) ((char*) mem + sizeof(lsptr)) ; ((lsptr*) mem)->ls = ls ; mcx_link_init(lk, val) ; return lk ; } mcxLink* mcxListSource ( dim capacity_start , mcxbits options ) { mcx_list* ls ; if (!(ls = mcxAlloc(sizeof(mcx_list), RETURN_ON_FAIL))) return NULL #if DEBUG ; fprintf (stderr, "new list ptr <%p> capacity <%ld>\n", (void*) ls, (long) capacity_start) #endif ; if (! (ls->grim = mcxGrimNew(sizeof(lsptr) + sizeof(mcxLink), capacity_start, options) ) ) return NULL ; return mcx_list_shift(ls, NULL) ; } mcxLink* mcxLinkSpawn ( mcxLink* lk , void* val ) { mcx_list* ls = mcx_list_find(lk) ; return mcx_list_shift(ls, val) ; } void mcxLinkClose ( mcxLink* left , mcxLink* right ) { if (left) left->next = right ; if (right) right->prev = left ; } mcxLink* mcxLinkBefore ( mcxLink* next , void* val ) { mcx_list* ls = mcx_list_find(next) ; mcxLink* new = mcx_list_shift(ls, val) ; if (!new) return NULL ; new->next = next ; new->prev = next->prev ; next->prev = new ; if (new->prev) new->prev->next = new ; return new ; } mcxLink* mcxLinkAfter ( mcxLink* prev , void* val ) { mcx_list* ls = mcx_list_find(prev) ; mcxLink* new #if DEBUG ; fprintf(stderr, "list ptr <%p>\n", (void*) ls) #endif ; new = mcx_list_shift(ls, val) ; if (!new) return NULL ; new->prev = prev ; new->next = prev->next ; prev->next = new ; if (new->next) new->next->prev = new ; return new ; } void mcxLinkRemove ( mcxLink* lk ) { mcx_list* ls = mcx_list_find(lk) ; mcxGrimLet(ls->grim, ((char*) lk) - sizeof(lsptr)) ; } mcxLink* mcxLinkDelete ( mcxLink* lk ) { mcx_list* ls = mcx_list_find(lk) ; mcxLink* prev = lk->prev ; mcxLink* next = lk->next ; if (prev) prev->next = next ; if (next) next->prev = prev ; mcxGrimLet(ls->grim, ((char*) lk) - sizeof(lsptr)) ; return lk ; } mcxGrim* mcxLinkGrim ( mcxLink* lk ) { mcx_list* ls = mcx_list_find(lk) ; return ls->grim ; } void mcxListFree ( mcxLink** lkp , void freeval(void* valpp) cpl__unused /* (yourtype1** valpp) */ ) { if (*lkp) { mcx_list* ls = mcx_list_find(*lkp) ; mcxGrimFree(&(ls->grim)) ; mcxFree(ls) ; *lkp = NULL ; } ; } #undef DEBUG zoem-11-166/util/gralloc.c0000644000402500021140000000775711147246035012262 00000000000000/* (c) Copyright 2004, 2005, 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #include "alloc.h" #include "gralloc.h" /* TODO * calloc stuff. * implement arithmetic capacity strategy. */ #define DEBUG 0 typedef struct memnext { struct memnext* next ; } memnext ; /* future idea; use higher bita as perbytage style coefficients. duh. */ #define n1(grim) ((grim->flags >> 16) & 0xFF) #define n2(grim) ((grim->flags >> 24) & 0xFF) typedef struct grim_buf { char* units /* n_units * (sizeof(memnext) + sz_unit) */ ; dim n_units /* number of units available for this struct */ ; struct grim_buf* prev ; } grim_buf ; struct mcxGrim { grim_buf* buf ; dim sz_unit /* size of one unit */ ; memnext* na /* next available */ ; dim ct /* number in use */ ; mcxbits flags /* allocation strategy, numbers */ ; } ; grim_buf* grim_buf_new ( dim sz_unit , dim n_units ) { dim i ; grim_buf* buf ; char* units ; dim sz_load = sizeof(memnext) + sz_unit ; if (!(buf = mcxAlloc(sizeof(grim_buf), RETURN_ON_FAIL))) return NULL ; if ( !(buf->units = units = mcxAlloc(n_units * sz_load, RETURN_ON_FAIL) ) ) { mcxFree(buf) ; return NULL ; } buf->prev = NULL ; buf->n_units = n_units #if DEBUG ; fprintf (stderr, "Extending grim with <%lu> units\n", (ulong) n_units); #endif ; for (i=0;inext = (memnext*) (units + (i+1) * sz_load) ; ((memnext*) (buf->units + (n_units-1) * sz_load))->next = NULL ; return buf ; } mcxGrim* mcxGrimNew ( dim sz_unit , dim n_units , mcxbits options ) { mcxGrim* src = mcxAlloc(sizeof(mcxGrim), RETURN_ON_FAIL) ; if (!src) return NULL ; if (!(src->buf = grim_buf_new(sz_unit, n_units))) { mcxFree(src) ; return NULL ; } src->buf->prev = NULL ; src->flags = options ; src->na = (void*) src->buf->units ; src->ct = 0 ; src->sz_unit = sz_unit ; return src ; } dim mcxGrimMemSize ( mcxGrim* src ) { grim_buf *buf = src->buf, *this = buf->prev ; dim n = buf->n_units ; while (this) n += this->n_units , this = this->prev ; return n ; } mcxbool mcx_grim_extend ( mcxGrim* src ) { grim_buf* prevbuf = src->buf->prev ; dim n_units = prevbuf ? 2 * prevbuf->n_units : src->buf->n_units #if DEBUG ; dim t = mcxGrimMemSize(src) ; fprintf(stderr, "have %lu units\n", (ulong) t) #endif ; grim_buf* newbuf = grim_buf_new(src->sz_unit, n_units) ; if (!newbuf) return FALSE ; newbuf->prev = src->buf->prev ; src->buf->prev = newbuf ; src->na = (void*) newbuf->units /* fixme cast */ ; return TRUE ; } void mcxGrimFree ( mcxGrim** srcp ) { grim_buf *this = (*srcp)->buf ; while (this) { grim_buf* tmp = this->prev ; mcxFree(this->units) ; mcxFree(this) ; this = tmp ; } mcxFree(*srcp) ; *srcp = NULL ; } void mcxGrimLet ( mcxGrim* src , void* mem ) { memnext* na = (void*) ((char*) mem - sizeof(memnext)) ; na->next = src->na ; src->na = na ; src->ct-- ; } void* mcxGrimGet ( mcxGrim* src ) { void* mem ; if (!src->na && !mcx_grim_extend(src)) return NULL ; mem = ((char*) src->na) + sizeof(memnext) ; src->na = src->na->next ; src->ct++ ; return mem ; } dim mcxGrimCount ( mcxGrim* src ) { return src->ct ; } zoem-11-166/util/tok.c0000644000402500021140000001531711352514546011426 00000000000000/* (C) Copyright 2005, 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ /* TODO allow empty args () */ #include #include #include #include "tok.h" #include "types.h" #include "ting.h" #include "ding.h" #include "err.h" #include "alloc.h" #include "compile.h" #ifndef DEBUG # define DEBUG 0 #else # define DEBUG_DEFINED #endif char* mcxTokSkip ( const char* offset , int (*fbool)(int c) , ofs len ) { return mcxStrChrAint(offset, fbool, len) ; } /* * Accounts for nesting. * Will do '}', ')', ']', '>', assuming one of several conventions. * Does not handle string arguments with embedded delimiters, e.g. "foo) bar" */ mcxstatus mcxTokMatch ( const char* str_search , char** endptr , mcxbits mode , ofs len /* considered if >= 0 */ ) { const char* offset= str_search ; unsigned char c = *offset ; mcxstatus status = STATUS_OK ; mcxTing* stack ; const char* z ; *endptr = NULL ; if (len < 0) len = strlen(offset) ; z = offset + len ; switch(c) { case '{' : case '(' : case '[' : break ; default : mcxErr("mcxTokMatch", "not my coal of char <%c>", (int) c) ; return STATUS_FAIL ; } if (!(stack = mcxTingEmpty(NULL, 80))) return STATUS_FAIL ; do { unsigned char m = '\0' ; c = *offset ; switch(c) { case '{' : case '(' : case '[' : status = mcxTingTackc(stack, c) ; break ; case ')' : m = '(' ; break ; case '}' : m = '{' ; break ; case ']' : m = '[' ; break ; } if (m) status = mcxTingTickc(stack, m) ; if (status) break ; if (!stack->len) break ; offset++ ; } while (offset < z) ; if (stack->len) status = STATUS_FAIL ; else if (!status) *endptr = (char* )offset ; if (status) mcxErr ( "mcxTokMatch" , "stacklen <%lu>, offset <%ld>, char <%c>" , (ulong) stack->len , (long) (offset - str_search) , (int) *offset ) ; mcxTingFree(&stack) ; return status ; } mcxstatus mcxTokFind ( const char* offset , char* tok /* Only tok[0] considered for now! */ , char** pos , mcxbits mode cpl__unused , ofs len /* considered if >= 0 */ ) { mcxstatus status = STATUS_OK ; const char* x = offset, *z ; char *y = NULL ; if (len < 0) len = strlen(offset) ; z = offset + len ; *pos = NULL ; while (x < z) { if (*x == tok[0]) break ; switch(*x) { case '(' : case '{' : case '[' : if (!(status = mcxTokMatch(x, &y, 0, z-x))) x = y+1 ; break ; default : x++ ; break ; } if (status) break ; } if (!status) { *pos = (char*) x ; return *x == tok[0] ? STATUS_OK : STATUS_DONE ; } return STATUS_FAIL ; } void mcxTokFuncFree ( mcxTokFunc* tf ) { mcxTingFree(&(tf->key)) ; mcxListFree(&(tf->args), mcxTingFree_v) ; } mcxstatus mcxTokExpectFunc ( mcxTokFunc* tf , const char* str , dim str_len , char** z_pp , int n_min , int n_max , int *n_args ) { const char* me = "mcxTokExpectFunc" ; const char *z = str + str_len ; char *x = mcxTokSkip(str, isspace, str_len) /* signed issue */ ; char *y ; mcxTing* key = mcxTingEmpty(NULL, 20) ; mcxTing* args = mcxTingEmpty(NULL, 40) ; mcxstatus status = STATUS_FAIL ; mcxLink* src = NULL ; int ct = 0 ; *z_pp = NULL ; tf->key = NULL ; tf->args = NULL ; if (n_args) *n_args = 0 ; do { if (!x) { mcxErr(me, "no identifier at EOS") ; break ; } y = mcxStrChrAint(x, isalpha, z-x) ; if (y==x) { mcxErr(me, "expect identifier: <%s>", x) ; break ; } if (!y) { mcxErr(me, "lost identifier: <%s>", x) ; break ; } mcxTingNWrite(key, x, y-x) ; x = mcxTokSkip(y, isspace, z-y) ; if (!x || *x != '(') { mcxErr(me, "expect parenthesis: <%s>", x ? x : "EOS") ; break ; } if (mcxTokMatch(x, &y, 0, z-x)) { mcxErr(me, "error parsing <%s>", x) ; break ; } mcxTingNWrite(args, x+1, y-x-1) ; if (!(src = mcxTokArgs(args->str, args->len, &ct, tf->opts))) break ; if ( ( n_min >= 0 && ct < n_min ) || ( n_max >= 0 && ct > n_max ) ) { mcxErr ( me , "for key <%s>, arg count %d conflicts min/max %d/%d" , key->str , ct, n_min, n_max ) ; break ; } *z_pp = y+1 ; status = STATUS_OK ; } while (0) ; mcxTingFree(&args) ; if (status) { mcxTingFree(&key) ; mcxListFree(&src, mcxTingFree_v) ; } else { tf->key = key ; tf->args = src ; if (n_args) *n_args = ct ; } return status ; } mcxLink* mcxTokArgs ( const char* str , long str_len , int* n_args , mcxbits opts ) { mcxLink* src = mcxListSource(8, MCX_GRIM_ARITHMETIC) ; mcxLink* lk = src ; const char* x = str ; char* y = NULL ; const char* z = str + str_len ; mcxTing* arg = NULL ; int ct = 0 ; mcxstatus status = STATUS_FAIL ; while ((status = mcxTokFind(x, ",", &y, 0, z-x)) == STATUS_OK || y) { const char* l = x, *r = y ; if (opts & MCX_TOK_DEL_WS) { l = mcxStrChrAint(x, isspace, y-x) ; r = mcxStrRChrAint(x, isspace, y-x) ; if (l && r && l<=r) r++ ; else r = l = x ; } arg = mcxTingNNew(l, r-l) #if DEBUG ;fprintf(stderr, "adding <%s> [%d/ /%s]\n", arg->str, status, y) #endif ; lk = mcxLinkAfter(lk, arg) ; x = y+1 ; ct++ ; if (status) break ; } if (!y) { mcxErr("mcxTokArgs", "error occurred") ; mcxListFree(&src, mcxTingFree_v) ; return NULL ; } *n_args = ct ; return src ; } #ifndef DEBUG_DEFINED # undef DEBUG #else # undef DEBUG_DEFINED #endif zoem-11-166/util/ting.c0000644000402500021140000004667411147246115011600 00000000000000/* (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #include #include #include #include #include "../config.h" #include "ting.h" #include "ding.h" #include "minmax.h" #include "alloc.h" #include "array.h" #include "hash.h" #include "types.h" #include "err.h" #include "tr.h" void mcxTingRelease ( void* tingv ) { if (tingv && ((mcxTing*)tingv)->str) mcxFree(((mcxTing*)tingv)->str) ; } void mcxTingFree ( mcxTing **tingpp ) { mcxTing* ting = *tingpp ; if (ting) { if (ting->str) mcxFree(ting->str) ; mcxFree(ting) ; *tingpp = NULL ; } } void mcxTingFree_v ( void *tingpp ) { mcxTingFree((mcxTing**) tingpp) ; } #if 0 void mcxTingAbandon ( void *tingpp ) { mcxTing* ting = *((mcxTing**) tingpp) ; mcxFree(ting) ; } #endif mcxTing* mcxTingShrink ( mcxTing* ting , ofs offset ) { if (offset < 0) offset = ting->len + offset /* fixme conversion? */ ; if (offset < 0 || (dim) offset > ting->len) { mcxErr ( "mcxTingShrink" , "funny offset <%lu> newlen <%ld> combo" , (ulong) ting->len , (long) offset ) ; return ting ; } else { *(ting->str+offset) = '\0' ; ting->len = offset; ; } return ting ; } mcxTing* mcxTingEnsure ( mcxTing* ting , dim len ) { if (!ting && !(ting = (mcxTing*) mcxTingInit(NULL))) return NULL ; if (len <= ting->mxl) ; else { char* t = mcxRealloc(ting->str, len+1, RETURN_ON_FAIL) ; if (!t) return NULL ; ting->str = t ; ting->mxl = len ; if (1) *(ting->str+ting->mxl) = '\0' /* there should be no need to do this; * and for large allocations this may fail. */ ; } return ting ; } #ifndef HAVE_VA_COPY #define HAVE_VA_COPY 1 #endif /* todo nul hardening */ static mcxTing* mcx_ting_print ( mcxTing* dst , const char* fmt , va_list *args ) #define PRINT_BUF_SIZE 512 { char buf[PRINT_BUF_SIZE], *src ; mcxTing* txtbuf = NULL ; dim m = PRINT_BUF_SIZE ; int npf /* Perhaps hook this #definery with configure options that * benefit from autoconf machinery. */ #if HAVE_VA_COPY ; va_list args2 ; va_copy(args2, *args) ; npf = vsnprintf(buf, PRINT_BUF_SIZE, fmt, args2) ; va_end(args2) #else ; npf = vsnprintf(buf, PRINT_BUF_SIZE, fmt, *args) #endif /* from reading standards it seems that npf >= PRINT_BUF_SIZE * should be sufficient. However, alpha OSF1 provides * a counterexample. And from reading standard annotations * it seems that vsnprintf is widely ill-implemented */ ; if (npf < 0 || npf >= PRINT_BUF_SIZE - 1) { m = (npf >= 0 && npf >= PRINT_BUF_SIZE - 1) ? ((dim) npf) + 1 : 2 * m /* Suppose m is set to npf+1. Then mcxTingEmpty will malloc npf+2 * bytes and vnsprintf is given m+1=npf+2 as size argument, * which is > PRINT_BUF_SIZE. */ ; while (1) { if (!(txtbuf = mcxTingEmpty(txtbuf, m))) { mcxTingFree(&txtbuf) ; return NULL ; } #if HAVE_VA_COPY va_copy(args2, *args) ; npf = vsnprintf(txtbuf->str, m+1, fmt, args2) ; va_end(args2) #else ; npf = vsnprintf(txtbuf->str, m+1, fmt, *args) #endif /* Only the npf < 0 case is expected below. * The other check is defensive coding. We gave * vsnprintf m+1 as size argument, so the check is * against one less than that (alpha OSF1 example). */ ; if (npf < 0 || (dim) npf >= m) m *= 2 ; else break ; } src = txtbuf->str ; } else src = buf ; dst = mcxTingWrite(dst, src) ; mcxTingFree(&txtbuf) ; return dst ; } mcxTing* mcxTingPrintSplice ( mcxTing* dst , ofs offset , ofs delete , const char* fmt , ... ) { va_list args ; mcxTing *infix = NULL ; va_start(args, fmt) ; infix = mcx_ting_print(NULL, fmt, &args) ; va_end(args) ; if (!infix) return NULL ; if (!dst) return infix ; if ( mcxTingSplice(dst, infix->str, offset, delete, infix->len) != STATUS_OK ) { mcxTingFree(&infix) ; return NULL ; } mcxTingFree(&infix) ; return dst ; } mcxTing* mcxTingPrint ( mcxTing* dst , const char* fmt , ... ) { va_list args ; va_start(args, fmt) ; dst = mcx_ting_print(dst, fmt, &args) ; va_end(args) ; return dst ; } mcxTing* mcxTingPrintAfter ( mcxTing* dst , const char* fmt , ... ) { va_list args ; mcxTing *affix = NULL ; va_start(args, fmt) ; affix = mcx_ting_print(affix, fmt, &args) ; va_end(args) ; if (!dst) return affix ; if (!affix) /* presumably malloc failure */ return NULL ; if (!mcxTingAppend(dst, affix->str)) { mcxTingFree(&affix) ; return NULL ; } mcxTingFree(&affix) ; return dst ; } static const char* roman[40] = { "" , "i" , "ii", "iii", "iv" , "v" , "vi", "vii", "viii", "ix" , "" , "x" , "xx", "xxx", "xl" , "l" , "lx", "lxx", "lxxx", "xc" , "" , "c" , "cc", "ccc", "cd" , "d" , "dc", "dcc", "dccc", "cm" , "" , "m" , "mm", "mmm", "mmmm", "" , "" , "", "", "" } ; mcxTing* mcxTingRoman ( mcxTing* dst , long a , mcxbool ucase ) { long i, x, c, m ; char* p ; if (a >= 5000 || a <= 0) return mcxTingWrite(dst, "-") ; i = a % 10 ; a /= 10 ; x = a % 10 ; a /= 10 ; c = a % 10 ; a /= 10 ; m = a ; dst = mcxTingPrint ( dst , "%s%s%s%s" , roman[30+m] , roman[20+c] , roman[10+x] , roman[ 0+i] ) ; if (dst && ucase) for (p=dst->str;pstr+dst->len;p++) *p += 'A' - 'a' ; return dst ; } mcxTing* mcxTingDouble ( mcxTing* dst , double x , int decimals ) { char num[500] ; char* p ; int len = snprintf(num, 500, "%.*f", decimals, x) ; if (decimals < 0) { mcxErr("mcxTingDouble PBD", "negative decimals arg") ; decimals = 6 ; } if (len < 0 || len >= 500) return mcxTingWrite(dst, "[]") ; p = num+len-1 /* GNU libcx bug workaround */ /* it returns 2 for length of 'inf' */ ; if (decimals && strcmp(num, "inf")) { while (*p == '0') p-- ; if (*p == '.') *++p = '0' ; *++p = '\0' ; } return mcxTingWrite(dst, num) ; } mcxTing* mcxTingInteger ( mcxTing* dst , long x ) { char num[128] ; int len = snprintf(num, 128, "%ld", x) ; if (len < 0 || len >= 128) return mcxTingWrite(dst, "[]") ; return mcxTingWrite(dst, num) ; } void* mcxTingInit ( void * tingv ) { mcxTing *ting = tingv ; if (!ting) { if (!(ting = mcxAlloc(sizeof(mcxTing), RETURN_ON_FAIL))) return NULL ; } if (!(ting->str = (char*) mcxAlloc(sizeof(char), RETURN_ON_FAIL))) return NULL ; *(ting->str+0) = '\0' ; ting->len = 0 ; ting->mxl = 0 ; return ting ; } /* * Take string into an existing ting or into a new ting */ mcxTing* mcxTingInstantiate ( mcxTing* ting , const char* string ) /* strnotice strlen */ { dim length = string ? strlen(string) : 0 /* ensure handles ting==NULL and/or length==0 cases */ ; if (!(ting = mcxTingEnsure(ting, length))) return NULL /* strnotice strncpy */ ; if (string) { strncpy(ting->str, string, length) ; *(ting->str+length) = '\0' ; } ting->len = length ; return ting ; } int mcxTingRevCmp ( const void* t1 , const void* t2 ) { return (strcmp(((mcxTing*)t2)->str, ((mcxTing*)t1)->str)) ; } int mcxTingCmp ( const void* t1 , const void* t2 ) { return (strcmp(((mcxTing*)t1)->str, ((mcxTing*)t2)->str)) ; } int mcxTingPCmp ( const void* t1 , const void* t2 ) { return (strcmp(((mcxTing**)t1)[0]->str, ((mcxTing**)t2)[0]->str)) ; } int mcxTingPRevCmp ( const void* t1 , const void* t2 ) { return (strcmp(((mcxTing**)t2)[0]->str, ((mcxTing**)t1)[0]->str)) ; } int mcxPKeyTingCmp ( const void* k1 , const void* k2 ) { return strcmp ( ((mcxTing*) ((mcxKV**)k1)[0]->key)->str , ((mcxTing*) ((mcxKV**)k2)[0]->key)->str ) ; } int mcxPKeyTingRevCmp ( const void* k1 , const void* k2 ) { return strcmp ( ((mcxTing*) ((mcxKV**)k2)[0]->key)->str , ((mcxTing*) ((mcxKV**)k1)[0]->key)->str ) ; } mcxstatus mcxTingSplice ( mcxTing* ting , const char* pstr , ofs offset , ofs n_delete , dim n_copy ) { dim newlen ; if (!ting) { mcxErr("mcxTingSplice PBD", "void ting argument") ; return STATUS_FAIL ; } /* offset -1 denotes appending at the end, * offset -2 denotes inserting at the last-but-one position. * etc */ if (offset < 0) { if ((dim) -offset > ting->len + 1) offset = 0 ; else offset = ting->len + offset + 1 ; } else if ((dim) offset > ting->len) offset = ting->len ; if (n_delete == TING_INS_CENTER) { n_delete = MCX_MIN(ting->len, n_copy) ; offset = (ting->len - n_delete) / 2 /* n_delete <= ting->len */ ; } else if (n_delete == TING_INS_OVERWRITE) n_delete = MCX_MIN(ting->len - offset, n_copy) /* offset <= ting->len */ ; else if (n_delete == TING_INS_OVERRUN || n_delete < 0) n_delete = ting->len - offset /* offset <= ting->len */ ; else if (n_delete < 0) { mcxErr ( "mcxTingSplice PBD" , "unsupported delete mode %ld" , (long) n_delete ) ; return STATUS_FAIL ; } else if ((dim) (offset + n_delete) > ting->len) n_delete = ting->len - offset ; if (ting->len + n_copy < (dim) n_delete) /* now spurious? */ { mcxErr("mcxTingSplice PBD", "arguments result in negative length") ; return STATUS_FAIL ; } /* * essential: mcxSplice does not know to allocate room for '\0' */ newlen = ting->len - n_delete + n_copy ; if (!mcxTingEnsure(ting, newlen)) return STATUS_FAIL ; if ( mcxSplice ( &(ting->str) , pstr , sizeof(char) , &(ting->len) , &(ting->mxl) , offset , (dim) n_delete , n_copy ) != STATUS_OK ) return STATUS_FAIL /* * essential: mcxSplice might have realloced, so has to be done afterwards. */ ; *(ting->str+newlen) = '\0' ; if (ting->len != newlen) { mcxErr("mcxTingSplice panic", "mcxSplice gives unexpected result") ; return STATUS_FAIL ; } return STATUS_OK ; } mcxTing* mcxTingNew ( const char* str ) { return mcxTingInstantiate(NULL, str) ; } mcxTing* mcxTingNNew ( const char* str , dim sz ) { mcxTing* ting = mcxTingEnsure(NULL, sz) ; if (!ting) return NULL /* strnotice memcpy */ ; if (str && sz) memcpy(ting->str, str, sz) ; *(ting->str+sz) = '\0' ; ting->len = sz ; return ting ; } mcxTing* mcxTingEmpty ( mcxTing* ting , dim len ) { if (!(ting = mcxTingEnsure(ting, len))) return NULL ; *(ting->str+0) = '\0' , ting->len = 0 ; return ting ; } mcxTing* mcxTingWrite ( mcxTing* ting , const char* str ) { return mcxTingInstantiate(ting, str) ; } mcxTing* mcxTingNWrite ( mcxTing* ting , const char* str , dim sz ) { if (!(ting = mcxTingEnsure(ting, sz))) return NULL /* strnotice strncpy */ ; memcpy(ting->str, str, sz) ; *(ting->str+sz) = '\0' ; ting->len = sz ; return ting ; } char* mcxTingSubStr ( const mcxTing* ting , ofs offset , ofs length ) { char* str ; if (offset < 0 || (dim) offset > ting->len) offset = ting->len ; if (length < 0 || (dim) (offset+length) > ting->len) length = ting->len - offset ; if (!(str = mcxAlloc((dim) (length+1), RETURN_ON_FAIL))) return NULL ; if (length) memcpy(str, ting->str+offset, (dim) length) ; *(str+length) = '\0' ; return str ; } mcxTing* mcxTingify ( char* str ) { mcxTing* ting = mcxAlloc(sizeof(mcxTing), RETURN_ON_FAIL) ; ting->str = str /* strnotice strlen; ? tingify2 */ ; ting->len = strlen(str) ; return ting ; } char* mcxTinguish ( mcxTing* ting ) { char* str = ting->str ; mcxFree(ting) ; return str ; } char* mcxTingStr ( const mcxTing* ting ) { ofs slen = ting->len ; return mcxTingSubStr(ting, 0, slen) ; } mcxTing* mcxTingAppend ( mcxTing* ting , const char* str ) { if (!ting) return mcxTingNew(str) /* strnotice strlen */ ; if ( mcxTingSplice ( ting , str , -1 /* splice offset */ , 0 /* delete nothing */ , str? strlen(str) : 0 /* string length */ ) != STATUS_OK ) return NULL ; return ting ; } mcxTing* mcxTingKAppend ( mcxTing* ting , const char* str , dim sz ) { dim len = strlen(str) ; if (!ting && !sz) return mcxTingEmpty(NULL, 0) ; if (!sz) return ting ; while (sz-- > 0) /* careful with unsignedness */ if (!(ting = mcxTingNAppend(ting, str, len))) return NULL ; return ting ; } mcxTing* mcxTingNAppend ( mcxTing* ting , const char* str , dim sz ) { if (!ting) return mcxTingNWrite(NULL, str, sz) ; if ( mcxTingSplice ( ting , str , -1 /* splice offset */ , 0 /* delete nothing */ , sz ) != STATUS_OK ) return NULL ; return ting ; } mcxTing* mcxTingInsert ( mcxTing* ting , const char* str , ofs offset ) { if (!ting) return mcxTingNew(str) /* strnotice strlen */ ; if ( mcxTingSplice ( ting , str , offset /* splice offset */ , 0 /* delete nothing */ , str ? strlen(str) : 0 /* string length */ ) != STATUS_OK ) return NULL ; return ting ; } mcxTing* mcxTingNInsert ( mcxTing* ting , const char* str , ofs offset , dim length ) { if (!ting) return mcxTingNWrite(NULL, str, length) ; if ( mcxTingSplice ( ting , str , offset /* splice offset */ , 0 /* delete nothing */ , length /* length of str */ ) != STATUS_OK ) return NULL ; return ting ; } mcxTing* mcxTingDelete ( mcxTing* ting , ofs offset , dim width ) { ofs swidth = width ; if (!ting) return NULL ; if ( mcxTingSplice ( ting , NULL , offset /* splice offset */ , swidth /* delete width */ , 0 /* string length */ ) != STATUS_OK ) return NULL ; return ting ; } u32 mcxTingDJBhash ( const void* ting ) { return(mcxBJhash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingBDBhash ( const void* ting ) { return(mcxBDBhash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingBJhash ( const void* ting ) { return(mcxBJhash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingCThash ( const void* ting ) { return(mcxCThash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingDPhash ( const void* ting ) { return(mcxDPhash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingGEhash ( const void* ting ) { return(mcxGEhash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingOAThash ( const void* ting ) { return(mcxOAThash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingELFhash ( const void* ting ) { return(mcxELFhash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingFNVhash ( const void* ting ) { return(mcxFNVhash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 (*mcxTingHFieByName(const char* id))(const void* ting) { if (!strcmp(id, "dp")) return mcxTingDPhash ; else if (!strcmp(id, "bj")) return mcxTingBJhash ; else if (!strcmp(id, "elf")) return mcxTingELFhash ; else if (!strcmp(id, "djb")) return mcxTingDJBhash ; else if (!strcmp(id, "bdb")) return mcxTingBDBhash ; else if (!strcmp(id, "ge")) return mcxTingGEhash ; else if (!strcmp(id, "oat")) return mcxTingOAThash ; else if (!strcmp(id, "svd")) return mcxTingSvDhash ; else if (!strcmp(id, "svd2")) return mcxTingSvD2hash ; else if (!strcmp(id, "svd1")) return mcxTingSvD1hash ; else if (!strcmp(id, "ct")) return mcxTingCThash ; else if (!strcmp(id, "fnv")) return mcxTingFNVhash ; else return NULL ; } u32 mcxTingSvDhash ( const void* ting ) { return(mcxSvDhash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingSvD2hash ( const void* ting ) { return(mcxSvD2hash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingSvD1hash ( const void* ting ) { return(mcxSvD1hash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } u32 mcxTingHash ( const void* ting ) { return(mcxDPhash(((mcxTing*) ting)->str, ((mcxTing*) ting)->len)) ; } /* Fails only for memory reason */ mcxstatus mcxTingTackc ( mcxTing* ting , unsigned char c ) { if (!ting || !mcxTingEnsure(ting, ting->len+1)) return STATUS_FAIL ; ting->str[ting->len] = c ; ting->str[ting->len+1] = '\0' ; ting->len += 1 ; return STATUS_OK ; } /* Fails if last char is not the same as c */ mcxstatus mcxTingTickc ( mcxTing* ting , unsigned char c ) { if (!ting || !ting->len) return STATUS_FAIL ; if ((unsigned char) ting->str[ting->len-1] == c) { mcxTingShrink(ting, -1) ; return STATUS_OK ; } return STATUS_FAIL ; } zoem-11-166/util/ding.c0000644000402500021140000002264511163160565011552 00000000000000/* (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #include #include #include #include #include #include "ding.h" #include "types.h" #include "alloc.h" #include "minmax.h" char* mcxStrDup ( const char* str ) { return mcxStrNDup(str, strlen(str)) ; } char* mcxStrNDup ( const char* str , dim n ) { char* rts = mcxAlloc(n+1, RETURN_ON_FAIL) ; if (rts) memcpy(rts, str, n) , rts[n] = '\0' ; return rts ; } dim mcxStrCountChar ( const char* p , char c , ofs len ) { const char* z = p ; dim ct = 0 ; z += (len >= 0) ? (dim) len : strlen(p) ; while (p= 0 ? p+offset : p + strlen(p) ; while (--z >= p && !fbool((unsigned char) *z)) ; return (char*) (z >= p ? z : NULL) ; } char* mcxStrRChrAint ( const char* p , int (*fbool)(int c) , ofs offset ) { const char* z = offset >= 0 ? p+offset : p + strlen(p) ; while (--z >= p && fbool((unsigned char) *z)) ; return (char*) (z >= p ? z : NULL) ; } const char* bit8[256] = { "00000000" , "00000001" , "00000010" , "00000011" , "00000100" , "00000101" , "00000110" , "00000111" , "00001000" , "00001001" , "00001010" , "00001011" , "00001100" , "00001101" , "00001110" , "00001111" , "00010000" , "00010001" , "00010010" , "00010011" , "00010100" , "00010101" , "00010110" , "00010111" , "00011000" , "00011001" , "00011010" , "00011011" , "00011100" , "00011101" , "00011110" , "00011111" , "00100000" , "00100001" , "00100010" , "00100011" , "00100100" , "00100101" , "00100110" , "00100111" , "00101000" , "00101001" , "00101010" , "00101011" , "00101100" , "00101101" , "00101110" , "00101111" , "00110000" , "00110001" , "00110010" , "00110011" , "00110100" , "00110101" , "00110110" , "00110111" , "00111000" , "00111001" , "00111010" , "00111011" , "00111100" , "00111101" , "00111110" , "00111111" , "01000000" , "01000001" , "01000010" , "01000011" , "01000100" , "01000101" , "01000110" , "01000111" , "01001000" , "01001001" , "01001010" , "01001011" , "01001100" , "01001101" , "01001110" , "01001111" , "01010000" , "01010001" , "01010010" , "01010011" , "01010100" , "01010101" , "01010110" , "01010111" , "01011000" , "01011001" , "01011010" , "01011011" , "01011100" , "01011101" , "01011110" , "01011111" , "01100000" , "01100001" , "01100010" , "01100011" , "01100100" , "01100101" , "01100110" , "01100111" , "01101000" , "01101001" , "01101010" , "01101011" , "01101100" , "01101101" , "01101110" , "01101111" , "01110000" , "01110001" , "01110010" , "01110011" , "01110100" , "01110101" , "01110110" , "01110111" , "01111000" , "01111001" , "01111010" , "01111011" , "01111100" , "01111101" , "01111110" , "01111111" , "10000000" , "10000001" , "10000010" , "10000011" , "10000100" , "10000101" , "10000110" , "10000111" , "10001000" , "10001001" , "10001010" , "10001011" , "10001100" , "10001101" , "10001110" , "10001111" , "10010000" , "10010001" , "10010010" , "10010011" , "10010100" , "10010101" , "10010110" , "10010111" , "10011000" , "10011001" , "10011010" , "10011011" , "10011100" , "10011101" , "10011110" , "10011111" , "10100000" , "10100001" , "10100010" , "10100011" , "10100100" , "10100101" , "10100110" , "10100111" , "10101000" , "10101001" , "10101010" , "10101011" , "10101100" , "10101101" , "10101110" , "10101111" , "10110000" , "10110001" , "10110010" , "10110011" , "10110100" , "10110101" , "10110110" , "10110111" , "10111000" , "10111001" , "10111010" , "10111011" , "10111100" , "10111101" , "10111110" , "10111111" , "11000000" , "11000001" , "11000010" , "11000011" , "11000100" , "11000101" , "11000110" , "11000111" , "11001000" , "11001001" , "11001010" , "11001011" , "11001100" , "11001101" , "11001110" , "11001111" , "11010000" , "11010001" , "11010010" , "11010011" , "11010100" , "11010101" , "11010110" , "11010111" , "11011000" , "11011001" , "11011010" , "11011011" , "11011100" , "11011101" , "11011110" , "11011111" , "11100000" , "11100001" , "11100010" , "11100011" , "11100100" , "11100101" , "11100110" , "11100111" , "11101000" , "11101001" , "11101010" , "11101011" , "11101100" , "11101101" , "11101110" , "11101111" , "11110000" , "11110001" , "11110010" , "11110011" , "11110100" , "11110101" , "11110110" , "11110111" , "11111000" , "11111001" , "11111010" , "11111011" , "11111100" , "11111101" , "11111110" , "11111111" } ; mcxTing* mcxMemPrint ( mcxTing* ting , void* p , dim n_bytes , mcxbits flags ) { char* m = p ; mcxbool space = !(flags & MCX_MEMPRINT_NOSPACE) ; mcxbool rev = flags & MCX_MEMPRINT_REVERSE ; dim i ; ting = mcxTingEmpty(ting, 32) ; for (i=0;i best) best = TBL(i+1,j+1) ; } *lcs = best ; } free(tbl) ; return min_val ; } int mcxSetenv ( const char* kv ) { mcxTing* tv = mcxTingNew(kv) ; if (!strchr(kv, '=')) mcxTingAppend(tv, "=1") ; return putenv(mcxTinguish(tv)) ; } mcxstatus mcxStrTol ( const char* s , long* value , char** end ) { int errno_sa = errno ; char* e = NULL ; mcxstatus status = STATUS_OK ; errno = 0 ; *value = strtol(s, &e, 10) ; if (errno || e == s) status = STATUS_FAIL ; errno = errno_sa ; if (end) *end = e ; return status ; } mcxstatus mcxStrToul ( const char* s , ulong* value , char** end ) { int errno_sa = errno ; mcxstatus status = STATUS_OK ; char* e = NULL ; errno = 0 ; *value = strtoul(s, &e, 10) ; if (errno || e == s) status = STATUS_FAIL ; errno = errno_sa ; if (end) *end = e ; return status ; } zoem-11-166/util/tr.c0000644000402500021140000005642011147246123011251 00000000000000/* (C) Copyright 2005, 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ /* TODO * - xtr_get_token does not check repeat pointer. crashable? * - something that translates \012 to the byte value. * - write regression test. * - More error codes * - Have a magic repeat operator that does not stop on boundaries. * - Do sane things to implicit \0 (e.g. as result of complement) and * characters outside ascii range. * - [*a*256] leads to count 0. * # tr a-z A-C[*#*]X-Z will not (now nor ever) lookahead * - what about alpha tr(1) capabilities? * 6. In the POSIX locale, to translate all ASCII characters that are not * specified, enter: * tr -c '[ -~]' '[A-_]' newfile */ /* NOTE - only room for 256 classes including sentinels C_CLASSSTART C_CLASSEND - during tlt phase delete and squash bits are ignored and not respected */ /* randomly located documentation of intermediate and final tbl formats * * css class start sentinel * ces class end sentinel * rps repeat sentinel * rss range start sentinel * res range end sentinel * * Class: * css | class , i1, i2, i3, .. , ces | class * where i1 etc are to be mapped * * Repeat: * rss | value, count * * Range * rss | _ , i, i+1, i+2, i+3, .. , res | _ * * Final tbl format: value stored in lower 8 bits. * Higher bits may contain MCX_TR_TRANSLATE, MCX_TR_DELETE MCX_TR_SQUASH */ #include #include #include #include #include "tr.h" #include "ting.h" #include "types.h" #include "ding.h" #include "err.h" const char* X_REPEAT_UNEXPECTED = "repeat unexpected"; const char* X_REPEAT_SYNTAX = "repeat syntax"; const char* X_CLASS_UNKNOWN = "class unknown"; const char* X_CLASS_UNEXPECTED = "class unexpected"; const char* X_OCTAL_RANGE = "octal range"; const char* X_OCTAL_SYNTAX = "octal syntax"; const char* X_HEX_RANGE = "hex range"; const char* X_HEX_SYNTAX = "hex syntax"; const char* X_RANGE_INVERTED = "inverted range"; const char* mcx_tr_err = NULL; mcxbool mcx_tr_debug = FALSE; #define MAX_SPEC_INDEX 511 #define error_break break #define UC(c) ((unsigned char) *(c)) static const char* us = "tr"; enum { C_CLASSSTART = 1u , C_ALNUM , C_ALPHA , C_CNTRL , C_DIGIT , C_GRAPH , C_LOWER , C_PRINT , C_PUNCT , C_SPACE , C_UPPER , C_XDIGIT , C_CLASSEND /* 13 */ , C_RANGESTART , C_RANGEEND , C_REPEAT /* next token encodes repeat (stops on boundary)*/ , C_FLOOD /* next token encodeÑ• flood (floods all) */ , C_EOF } ; #define ISCLASS(cl) ((cl) > C_CLASSSTART && (cl) < C_CLASSEND) #define ISREPEAT(cl) ((cl) == C_REPEAT || (cl) == C_FLOOD) #define ISUCHARRANGE(i) \ ( (i) >= 0 && (i) < 256 ) #define ISBOUNDARY(cl) \ ( (cl) == C_CLASSSTART || (cl) == C_CLASSEND \ || (cl) == C_RANGESTART || (cl) == C_RANGEEND ) #define ISSTART(cl) \ ( (cl) == C_CLASSSTART || (cl) == C_RANGESTART ) #define ISEND(cl) \ ( (cl) == C_CLASSEND || (cl) == C_RANGEEND ) #define ISUPPERSTART(tok) \ ( tok == ((C_CLASSSTART << 8) | C_UPPER) ) #define ISLOWERSTART(tok) \ ( tok == ((C_CLASSSTART << 8) | C_LOWER) ) int (*isit[13])(int c) = { NULL /* so C_CLASSVAL - C_CLASSSTART gives an index */ , isalnum , isalpha , iscntrl , isdigit , isgraph , islower , isprint , ispunct , isspace , isupper , isxdigit } ; mcxTing* mcxTRsplash ( mcxTR* tr , mcxbits bits ) { int i,j ; u32* tbl = tr->tlt ; mcxTing* splash = mcxTingEmpty(NULL, 256) ; for (i=1,j=0;i<256;i++) /* NOTE: \000 excluded */ { u32 tok = tbl[i] ; u32 meta = tok >> 8 ; if ( ((bits & MCX_TR_SOURCE) && (meta & MCX_TR_TRANSLATE)) || ((bits & MCX_TR_SOURCE_C) && ! (meta & MCX_TR_TRANSLATE)) || ((bits & MCX_TR_SQUASH) && (meta & MCX_TR_SQUASH)) || ((bits & MCX_TR_SQUASH_C) && ! (meta & MCX_TR_SQUASH)) || ((bits & MCX_TR_DELETE) && (meta & MCX_TR_DELETE)) || ((bits & MCX_TR_DELETE_C) && ! (meta & MCX_TR_DELETE)) ) splash->str[j++] = i ; } splash->str[j] = '\0' ; return splash ; } ofs mcxTRtranslate ( char* src , mcxTR* tr ) { dim i,j ; int prev = INT_MAX /* only relevant for squash case */ ; dim len = strlen(src) ; u32* tbl = tr->tlt ; for (i=0,j=0;i> 8) & MCX_TR_TRANSLATE ? idxmap : idx ; if ((tbl[val] >> 8) & MCX_TR_DELETE) continue ; if (!((tbl[val] >> 8) & MCX_TR_SQUASH) || val != prev) { *(src+j++) = (char) val ; prev = val ; } } *(src+j) = '\0' ; return (ofs) j ; } ofs mcxTingTranslate ( mcxTing* src , mcxTR* tr ) { src->len = mcxTRtranslate(src->str, tr) ; return src->len ; } /* fixme conceivably mcxTRtranslate could return -1 as * error condition. hum ho. */ ofs mcxTingTr ( mcxTing* txt , const char* src , const char* dst , const char* set_delete , const char* set_squash , mcxbits modes ) { mcxTR tr ; if (mcxTRloadTable(&tr, src, dst, set_delete, set_squash, modes)) return -1 ; txt->len = mcxTRtranslate(txt->str, &tr) ; return txt->len ; } static const char* xtr_get_token ( const char *p , const char *z , u8* classp , u8* valuep , int *repeat ) #define MCX_HEX(c) ( (c>='0' && c<='9') ? c-'0'\ : (c>='a' && c<='f') ? c-'a'+10\ : (c>='A' && c<='F') ? c-'A'+10\ : 0\ ) { int c = UC(p), d = 0, np = 0 ; mcxstatus status = STATUS_FAIL ; i32 value = 0, class = 0 /* need to be able to check overflow */ ; const char* me = "xtr_" "get_token" ; mcxbool class_ok = classp ? TRUE : FALSE ; if (classp) *classp = 0 ; if (valuep) *valuep = 0 ; if (repeat) *repeat = -1 ; while (1) { if (p >= z) break /*************************************************************************/ ; if (c == '\\') { if (p+1 >= z) error_break ; d = UC(p+1) ; if (strchr("0123", d)) { if ( p+3 >=z || !isdigit(UC(p+2)) || !isdigit(UC(p+3)) /* fixme 009 */ ) { mcx_tr_err = X_OCTAL_SYNTAX ; error_break ; } value = 64*(d-'0') + 8*(UC(p+2)-'0') + (UC(p+3)-'0') ; if (value > 0377) { mcx_tr_err = X_OCTAL_RANGE ; error_break ; } np = 4 ; } else if (d == 'x') { if ( p+3 >= z || !isxdigit(UC(p+2)) || !isxdigit(UC(p+3)) ) { mcx_tr_err = X_HEX_SYNTAX ; error_break ; } value = 16 * MCX_HEX(UC(p+2)) + MCX_HEX(UC(p+3)) ; np = 4 ; } else if (strchr("\\abfnrtv", d)) { np = 2 ; switch(d) { case 'a' : value = 07 ; break ; case 'b' : value = 010 ; break ; case 'f' : value = 014 ; break ; case 'n' : value = 012 ; break ; case 'r' : value = 015 ; break ; case 't' : value = 011 ; break ; case 'v' : value = 013 ; break ; case '\\': value = 0134; break ; default : value = '?' ; break /* impossible */ ; } } else { value= d ; np = 2 ; } } /* case '\\' */ /*************************************************************************/ else if (c == '[') { if (!class_ok) /* fixme: could just accept '[' */ { mcx_tr_err = X_CLASS_UNEXPECTED ; error_break ; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ else if (p+1 < z && UC(p+1) == ':') { if (!strncmp(p+2, "alpha:]", 7)) class = C_ALPHA, np = 4+ 5 ; else if (!strncmp(p+2, "alnum:]", 7)) class = C_ALNUM, np = 4+ 5 ; else if (!strncmp(p+2, "digit:]", 7)) class = C_DIGIT, np = 4+ 5 ; else if (!strncmp(p+2, "cntrl:]", 7)) class = C_CNTRL, np = 4+ 5 ; else if (!strncmp(p+2, "graph:]", 7)) class = C_GRAPH, np = 4+ 5 ; else if (!strncmp(p+2, "lower:]", 7)) class = C_LOWER, np = 4+ 5 ; else if (!strncmp(p+2, "print:]", 7)) class = C_PRINT, np = 4+ 5 ; else if (!strncmp(p+2, "punct:]", 7)) class = C_PUNCT, np = 4+ 5 ; else if (!strncmp(p+2, "space:]", 7)) class = C_SPACE, np = 4+ 5 ; else if (!strncmp(p+2, "upper:]", 7)) class = C_UPPER, np = 4+ 5 ; else if (!strncmp(p+2, "xdigit:]", 8)) class = C_XDIGIT, np = 4+ 6 ; else { mcx_tr_err = X_CLASS_UNKNOWN ; break ; } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ else if (p+1 < z && UC(p+1) == '*') { int num = 0 ; u8 value2 = 0 ; const char* q = NULL ; if (p+2 >= z) { mcx_tr_err = X_REPEAT_SYNTAX ; error_break ; } if (!(q = xtr_get_token(p+2, z, NULL, &value2, NULL))) error_break ; if (UC(q) == '*' && UC(q+1) == ']') class = C_FLOOD ; else if ( (UC(q) == '#' && UC(q+1) == ']') || (UC(q) == '*') ) class = C_REPEAT ; else { mcx_tr_err = X_REPEAT_SYNTAX ; error_break ; } if (UC(q+1) == ']') { *repeat = 0 ; q++ ; } else { if (sscanf(q+1, "%d]", &num) != 1) break ; if (!(q = strchr(q, ']'))) break ; if (num < 0 || num > 256) break ; *repeat = num ; if (!num) class = C_FLOOD ; } /* q[0] should be ']' now */ value = value2 ; np = (q+1) - p /* truncintok */ ; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ else break ; } /*************************************************************************/ else { value = c ; np = 1 ; } status = STATUS_OK ; break ; } if (status) { mcxErr(me, "error at char (%c)", UC(p)) ; return NULL ; } if (mcx_tr_debug) fprintf(stdout, "xtr_get_token (%d | %d)\n", (int) value, (int) class) ; if (classp) *classp = class ; if (valuep) *valuep = value ; return p + np ; } char* mcxStrEscapedValue ( const char* p , const char* z , int *value ) { u8 val = p[0] ; const char* q = NULL ; if (val != '\\') { *value = val ; return (char*) (p+1) ; } if (!(q = xtr_get_token(p, z, NULL, &val, NULL))) return NULL ; *value = val ; return (char*) q ; } /* Sets either * value to something in the range 0-255 and length * to something >= 1 * or * value to one of the constants C_ALPHA etc and length to 0. * * Returns the next parsable character or NULL for failure. */ static const char* xtr_get_set ( const char *p , const char *z , u8 *classp , u8 *valuep , int *countp ) { const char* q = xtr_get_token(p, z, classp, valuep, countp) ; if (!q) return NULL ; if (!*classp && *q == '-') { u8 range_top = 0 ; q = xtr_get_token(q+1, z, NULL, &range_top, NULL) ; if (!q) return NULL ; if (range_top < *valuep) { mcx_tr_err = X_RANGE_INVERTED ; return NULL ; } *countp = range_top - *valuep + 1 ; } else if (!*classp) *countp = 1 /* else it is a repeat class or .. */ ; return q ; } static void mcx_tr_enc_dump ( u32* enc , const char* tag ) { int i = 0 ; fprintf(stdout, "(dumping %s\n", tag) ; while (i> 8 ; int val = enc[i] & 0377 ; fprintf(stdout, "%6d%6d%6d\n", i, meta, val) ; if (meta == C_EOF) break ; i++ ; } fprintf(stdout, ")\n") ; } static mcxstatus xtr_get_spec ( const char* spec , u32* tbl /* size MAX_SPEC_INDEX+1 */ , mcxbool repeat_ok /* doubles as true for dst, false for src, ugly! */ ) { const char* p = spec ; const char* z = spec + strlen(spec) ; int offset=0, i=0 ; mcxstatus status = STATUS_FAIL ; while (1) { u8 value = 0 ; u8 class = 0 ; int count = -1 ; status = STATUS_OK ; if (p >= z) break ; status = STATUS_FAIL /* space for 1 token; check anything longer. * (reserve space for EOF token) */ ; if (offset >= MAX_SPEC_INDEX) break ; if (!(p = xtr_get_set(p, z, &class, &value, &count))) break ; if (ISREPEAT(class) && count >= 0) { if (!repeat_ok) { mcx_tr_err = X_REPEAT_UNEXPECTED ; break ; } tbl[offset++] = (class << 8) | value ; if (offset >= MAX_SPEC_INDEX) break ; tbl[offset++] = count & 0377 ; } else if (ISCLASS(class)) { int (*innit)(int) = isit[class - C_CLASSSTART] ; tbl[offset++] = (C_CLASSSTART << 8 ) | class ; for (i=0;i<256;i++) { if (innit(i)) { if (offset >= MAX_SPEC_INDEX) break ; tbl[offset++] = i ; } } if (i != 256) break ; if (offset >= MAX_SPEC_INDEX) break ; tbl[offset++] = (C_CLASSEND << 8) | class ; } else if (count > 1) { tbl[offset++] = (C_RANGESTART << 8) ; for (i=value;i= MAX_SPEC_INDEX) break ; tbl[offset++] = i ; } if (i != value+count) break ; if (offset >= MAX_SPEC_INDEX) break ; tbl[offset++] = C_RANGEEND << 8 ; } else tbl[offset++] = value ; status = STATUS_OK ; } tbl[offset++] = C_EOF << 8 ; if (status || p!=z) { mcxErr(us, "error!") ; return STATUS_FAIL ; } return STATUS_OK ; } static mcxstatus mcx_tr_encode_boolean ( mcxTR* tr , u32* enc , mcxbits bit ) { int i ; for (i=0;i> 8 ; int value = enc[i] & 0377 ; if (class == C_EOF) break ; if (class) continue ; tr->tlt[value] |= bit << 8 ; } return STATUS_OK ; } static mcxstatus mcx_tr_translate_encode ( mcxTR* tr , u32* srcenc , u32* dstenc ) { int X = -1, Y = -1 ; int s = 0, d = 0 ; int star_count = 0 ; mcxbool star_fill = FALSE , flood_fill = FALSE , src_end = FALSE , dst_end = FALSE , to_lower = FALSE , to_upper = FALSE , src_class_end = FALSE ; while (1) { u32 src_tok = 0 ; u32 src_cls = 0 ; u32 src_val = 0 ; u32 dst_tok = 0 ; u32 dst_cls = 0 ; u32 dst_val = 0 ; src_class_end = FALSE ; if (s >= MAX_SPEC_INDEX || d >= MAX_SPEC_INDEX) { mcxErr(us, "panic off the rails") ; break ; } if (X >= 0 && Y >= 0) { tr->tlt[X] = Y | (MCX_TR_TRANSLATE << 8) ;if (mcx_tr_debug) fprintf(stdout, "map %d to %d\n", X, Y) ; X = -1 ; if (star_count) star_count-- ; if (!star_count && !star_fill && !flood_fill) Y = -1 ; } else if (s || d) mcxErr(us, "fimbly feeling") /* skip ends, unset star_fill if necessary */ ; src_tok = srcenc[s++] ; src_cls = src_tok >> 8 ; src_val = src_tok & 0377 /* consider both * tring -x 'abcdef[:digit:]' -y '[*_#][*##]' (magic ends with f) * tring -x '[:digit:]abcdef' -y '[*##][*_#]' (magic ends before a) */ ; if (ISBOUNDARY(src_cls)) star_fill = FALSE ; if (ISEND(src_cls)) src_tok = srcenc[s++] , src_cls = src_tok >> 8 , src_val = src_tok & 0377 , src_class_end = TRUE ; if (!star_count && !star_fill && !flood_fill) { dst_tok = dstenc[d++] ; dst_cls = dst_tok >> 8 ; dst_val = dst_tok & 0377 ; if (ISEND(dst_cls)) dst_tok = dstenc[d++] , dst_cls = dst_tok >> 8 , dst_val = dst_tok & 0377 ; } ;if (mcx_tr_debug) fprintf(stdout, "have %3d %3d %3d %3d\n", (int) src_cls, (int) src_val, (int) dst_cls, (int) dst_val); /* check class/range conditions. */ if (ISLOWERSTART(src_tok) && ISUPPERSTART(dst_tok)) to_upper = TRUE ; else if (ISUPPERSTART(src_tok) && ISLOWERSTART(dst_tok)) to_lower = TRUE ; else if ((to_upper || to_lower) && src_class_end) to_lower = FALSE , to_upper = FALSE /* check repeat */ ; if (ISREPEAT(dst_cls)) { Y = dst_val ; star_count = dstenc[d++] ; if (dst_cls == C_FLOOD) flood_fill = TRUE ; else if (!star_count) star_fill = TRUE ;if (mcx_tr_debug) fprintf(stdout, "star count/fill/flood %d %d %d\n", star_count, star_fill, flood_fill) ; } ;if (mcx_tr_debug && (to_upper || to_lower)) fprintf(stdout, "case mapping\n") ; if (!star_count && !star_fill && !flood_fill) { if (ISSTART(dst_cls)) Y = dstenc[d++] ; else Y = dst_val ; } if (ISSTART(src_cls)) X = srcenc[s++] ; else X = src_val ; if (!ISUCHARRANGE(X) || !ISUCHARRANGE(Y)) mcxErr(us, "panic %d %d", X, Y) , X = 0 , Y = 0 ; if (to_lower) { if (!isupper(X)) { mcxErr(us, "panic %d not lower", X) ; X = 0, Y = 0 ; } else Y = tolower(X) ; } else if (to_upper) { if (!islower(X)) { mcxErr(us, "panic %d not upper", X) ; X = 0, Y = 0 ; } else Y = toupper(X) ; } src_end = src_cls == C_EOF ; dst_end = dst_cls == C_EOF ; if (src_end || dst_end) break ; } if (!src_end) mcxErr(us, "trailing fluff in src") ; if (!dst_end && !((star_fill || flood_fill) && dstenc[d] >> 8 == C_EOF)) mcxErr(us, "trailing fluff in dst") ; return STATUS_OK /* specs parsed alright, just ignore spurious stuff */ ; } static void mcx_tr_complement ( u32* enc ) { u32 tmp[256] ; int i = 0 ; int j = 0 ; int delta = 1 ; for (i=0;i<256;i++) tmp[i] = 0 ; for (i=0;i<=MAX_SPEC_INDEX;i+=delta) { int class = enc[i] >> 8 ; int value = enc[i] & 0377 ; if (ISREPEAT(class)) { delta = 2 ; mcxErr(us, "value taken but repeat ignored in complement") ; tmp[value] = 1 ; continue ; } else if (ISBOUNDARY(class)) /* nada */ ; else tmp[value] = 1 ; delta = 1 ; } for (i=0;i<256;i++) if (!tmp[i]) enc[j++] = i ; enc[j++] = C_EOF << 8 ; while (j<=MAX_SPEC_INDEX) enc[j++] = C_EOF << 8 ; } /* * the enc arrays use stop and end tokens for ranges and classes. both are * required to have more than 1 element. No more than MAX_SPEC_INDEX+1 * positions are allocated for either specification, which also cater for * start and end and EOF tokens - the +1 is for the EOF token. * * carryon */ static mcxstatus mcx_tr_encode ( mcxTR* tr , const char* src , const char* dst , const char* set_delete , const char* set_squash ) { u32 srcenc[MAX_SPEC_INDEX+1] ; u32 dstenc[MAX_SPEC_INDEX+1] ; int i ; if (src && dst) { for (i=0;i<=MAX_SPEC_INDEX;i++) srcenc[i] = 0 , dstenc[i] = 0 ; if (xtr_get_spec(src, srcenc, FALSE)) return STATUS_FAIL ; if (mcx_tr_debug) mcx_tr_enc_dump(srcenc, "source") ; if (tr->modes & MCX_TR_SOURCE_C) mcx_tr_complement(srcenc) ; if (xtr_get_spec(dst, dstenc, TRUE)) return STATUS_FAIL ; if (mcx_tr_debug) mcx_tr_enc_dump(dstenc, "destination") ; if (tr->modes & MCX_TR_DEST_C) mcx_tr_complement(dstenc) ; if (mcx_tr_translate_encode(tr, srcenc, dstenc)) return STATUS_FAIL ; } if (set_delete) { for (i=0;i<=MAX_SPEC_INDEX;i++) srcenc[i] = 0 ; if (xtr_get_spec(set_delete, srcenc, FALSE)) return STATUS_FAIL ; if (mcx_tr_debug) mcx_tr_enc_dump(srcenc, "delete") ; if (tr->modes & MCX_TR_DELETE_C) mcx_tr_complement(srcenc) ; mcx_tr_encode_boolean(tr, srcenc, MCX_TR_DELETE) ; } if (set_squash) { for (i=0;i<=MAX_SPEC_INDEX;i++) srcenc[i] = 0 ; if (xtr_get_spec(set_squash, srcenc, FALSE)) return STATUS_FAIL ; if (mcx_tr_debug) mcx_tr_enc_dump(srcenc, "squash") ; if (tr->modes & MCX_TR_SQUASH_C) mcx_tr_complement(srcenc) ; mcx_tr_encode_boolean(tr, srcenc, MCX_TR_SQUASH) ; } return STATUS_OK ; } mcxstatus mcxTRloadTable ( mcxTR* tr , const char* src , const char* dst , const char* set_delete , const char* set_squash , mcxbits modes ) { const char* me = "mcxTRloadTable" ; int i ; mcx_tr_err = NULL ; if (src && UC(src) == '^') src++ , modes |= MCX_TR_SOURCE_C ; if (dst && UC(dst) == '^') dst++ , modes |= MCX_TR_DEST_C ; if (src && dst) modes |= MCX_TR_TRANSLATE ; if (set_delete) { if (UC(set_delete) == '^') set_delete++ , modes |= MCX_TR_DELETE_C ; modes |= MCX_TR_DELETE ; } ; if (set_squash) { if (UC(set_squash) == '^') set_squash++ , modes |= MCX_TR_SQUASH_C ; modes |= MCX_TR_SQUASH ; } tr->modes = modes ; for (i=0;i<256;i++) tr->tlt[i] = 0 ; if (src && !dst) { mcxErr(me, "src requires dst") ; return STATUS_FAIL ; } return mcx_tr_encode(tr, src, dst, set_delete, set_squash) ; } zoem-11-166/util/types.c0000644000402500021140000000077611147246140011772 00000000000000/* (C) Copyright 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #include "types.h" const char* mcx_status_list[] = { "OK" , "FAIL" , "DONE" , "IGNORE" , "NOMEM" , "ABORT" , "NEW" , "UNUSED" } ; zoem-11-166/util/alloc.h0000644000402500021140000000365311147245271011726 00000000000000/* (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_alloc_h #define tingea_alloc_h #include /* ========================================================================= * * * mcxRealloc is notable, for it *frees* memory and returns a NULL pointer * if the newly requested block has size 0. This must be so in order to * allow routines to do their math and housekeeping. If they register the * new block as having 0 bytes, then they need not and must not attempt to * free it thereafter. * * ========================================================================= * */ #include "types.h" void* mcxAlloc ( dim size , mcxOnFail ON_FAIL ) ; void* mcxRealloc ( void* object , dim new_size , mcxOnFail ON_FAIL ) ; void mcxFree ( void* object ) ; void mcxNFree ( void* base , dim n_elem , dim elem_size , void (*obRelease) (void *) ) ; void* mcxNAlloc ( dim n_elem , dim elem_size , void* (*obInit) (void *) , mcxOnFail ON_FAIL ) ; void* mcxNRealloc ( void* mem , dim n_elem , dim n_elem_prev , dim elem_size , void* (*obInit) (void *) , mcxOnFail ON_FAIL ) ; void mcxMemDenied ( FILE* channel , const char* requestee , const char* unittype , dim n ) ; void mcxAllocLimits ( long maxchunksize , long maxtimes ) ; #endif zoem-11-166/util/array.h0000644000402500021140000000774711344153316011757 00000000000000/* (C) Copyright 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_array_h #define tingea_array_h #include "types.h" mcxstatus mcxSplice ( void* base1pp /* _address_ of pointer to elements */ , const void* base2p /* pointer to elements */ , dim size /* size of base1 and base2 members */ , dim *n_base1 /* total length of elements after base1 */ , dim *N_base1 /* number of alloc'ed elements for base1 */ , ofs o_base1 /* splice relative to this ofset */ , dim d_base1 /* delete this number of elements */ , dim c_base2 /* number of elements to copy */ ) ; dim mcxDedup ( void* base , dim nmemb , dim size , int (*cmp)(const void *, const void *) , void (*merge)(void *, const void *) ) ; mcxstatus mcxResize ( void* mempp , dim size , dim* ct , dim newct , mcxOnFail ON_FAIL ) ; /* Return largest element smaller than or equal to key. * return NULL if no element is smaller than key. * Returns rightmost element in case entries sort identically, * (note: mcxBsearchCeil will then return the leftmost element) * * base should be sorted according to cmp */ void* mcxBsearchFloor ( const void *key , const void *base , dim nmemb , dim size , int (*cmp)(const void *, const void *) ) ; /* Return smallest element larger than or equal to key. * return NULL if no element is larger than key. * Returns leftmost element in case entries sort identically, * (note: mcxBsearchFloor will then return the rightmost element) * * base should be sorted according to cmp */ void* mcxBsearchCeil ( const void *key , const void *base , dim nmemb , dim size , int (*cmp)(const void *, const void *) ) ; /* Uses weighted combinations of neighbours when the quartile * range does not fall perfectly on array offsets (i.e. * when the array size is not a multiple of 4. */ double mcxMedian ( void* base , dim n , dim sz , double (*get)(const void*) , double* iqr ) ; /* Fisher Yates shuffle */ void mcxShuffle ( void* datap , dim nmem , dim mem_size , char* mem_cell /* should have mem_size size */ ) ; typedef struct { void* mempptr ; dim size ; dim n ; dim n_alloc ; float factor ; mcxbool bFinalized ; } mcxBuf ; /* * *mempptr should be peekable; NULL or valid memory pointer. */ mcxstatus mcxBufInit ( mcxBuf* buf , void* mempptr , dim size , dim n ) ; /* * Extends the buffer by n_request unitialized chunks and returns a pointer * to this space. It is the caller's responsibility to treat this space * consistently. The counter buf->n is increased by n_request. * * If we cannot extend (realloc), a NULL pointer is returned; * the original space is left intact. * * Returns NULL on (alloc) failure */ void* mcxBufExtend ( mcxBuf* buf , dim n_request , mcxOnFail ON_FAIL ) ; /* * Make superfluous memory reclaimable by system, * prepare for discarding buf (but not *(buf->memptr)!) * * If for some bizarre reason we cannot shrink (realloc), * errno is set to ENOMEM. * the original space is left intact. Its size is in buf.n . */ dim mcxBufFinalize ( mcxBuf* buf ) ; /* * Make buffer refer to a new variable. Size cannot be changed, * so variable should be of same type as before. */ void mcxBufReset ( mcxBuf* buf , void* mempptr ) ; #endif zoem-11-166/util/rand.h0000644000402500021140000000226511147245542011557 00000000000000/* (C) Copyright 2004, 2005, 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_rand_h #define tingea_rand_h #include #define MCX_RAND_MAX RAND_MAX #define mcxUniform0 ((1.0 * random()) / ((double) RAND_MAX + 1.0)) #define mcxUniform1 (1.0 - ((1.0 * random()) / ((double) RAND_MAX + 1.0))) /* This is for weak seeding, to obtain fresh seeds which will definitely * *not* be suitable for cryptographic needs */ unsigned long mcxSeed ( unsigned long seedlet ) ; double mcxNormal ( void ) ; double mcxNormalCut ( double radius , double stddev ) ; double mcxNormalZiggurat ( void ) ; double mcxNormalBoxMuller ( void ) ; /* Generate numbers in the interval [-outer, outer] according * to the normal distribution with standard deviation sigma. * Use e.g. outer = 2.0 sigma = 0.5 */ double mcxNormalSample ( double radius , double stddev ) ; #endif zoem-11-166/util/equate.h0000644000402500021140000000302311147245325012107 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef equate_h #define equate_h int intCmp ( const void* i1 , const void* i2 ) ; int intRevCmp ( const void* i1 , const void* i2 ) ; int intnCmp ( const int* i1 , const int* i2 , int n ) ; int fltCmp ( const void* f1 , const void* f2 ) ; int fltRevCmp ( const void* f1 , const void* f2 ) ; int dblCmp ( const void* f1 , const void* f2 ) ; int dblRevCmp ( const void* f1 , const void* f2 ) ; int intLt ( const void* i1 , const void* i2 ) ; int intLq ( const void* i1 , const void* i2 ) ; int intGt ( const void* i1 , const void* i2 ) ; int intGq ( const void* i1 , const void* i2 ) ; int fltLt ( const void* f1 , const void* f2 ) ; int fltLq ( const void* f1 , const void* f2 ) ; int fltGt ( const void* f1 , const void* f2 ) ; int fltGq ( const void* f1 , const void* f2 ) ; #endif zoem-11-166/util/hash.h0000644000402500021140000002516711147245463011566 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_hash_h #define tingea_hash_h #include /* TODO: * - make sort routines for keys and values by key or value criteria. * - make interface for storing integers, preferably without objectifying them. * - shrink hashes dynamically. * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** Implementation notes (a few). * * * This hash interface is very powerful. It gives you more than enough * rope to hang yourself and then some. It can be used as is, or wrappers * can be made around it that restrict a caller's ability to err. * * The danger lies in the fact that this interface only does retrieval * and storage of pointers (both for keys and values), and does not clone * anything. Anything happening with the objects pointed to during the * lifetime of the hash is the responsibility of the caller. * * What the interface cannot do currently is hash integers by value (rather * than by reference). This functionality will probably be added someday. * Features: * o Searching, inserting, and deletion are all done by * mcxHashSearch. It returns a pointer to mcxKV. In all modes, the * caller can use the returned mcxKV* structure to obtain * the 'val' and 'key' members. * * o Hashes grow automatically once the average load per bucket * exceeds a settable threshold and if the hash was not declared * constant. * * o Caller supplies both the hash function and the compare function. * This interface provides several hash functions operating on a * (void* base, int len) combo, where base is cast to char by the * hash function. These functions can be used in creating custom hash * functions for your custom objects. * * o You can (of course) have multiple hashes. This is not really * a feature - however, since the idiotic does not offer * this I thought I'd mention it. * * o Witness mcxHashWalkInit, mcxHashWalkStep. * * o There is mcxHashMerge. * * o mcxHashKeys, mcxHashKVs. * * Enjoy. * Notes * There is a utility hashfile.c (distributed in a separate package) * that can be used to stress-test this module. It allows customization * of several aspects, including the hash function that should be used. */ #include "types.h" #include "list.h" /* The hash struct is hidden. Use mcxHashGetSettings if you need * to peek into the interior. Or read hash.c */ typedef struct mcxHash mcxHash; typedef struct { void* key ; void* val ; } mcxKV ; mcxHash* mcxHashNew ( dim n_buckets , u32 (*hash) (const void *a) , int (*cmp) (const void *a, const void *b) ) ; #define MCX_HASH_OPT_DEFAULTS 0 #define MCX_HASH_OPT_CONSTANT 1 #define MCX_HASH_OPT_UNUSED 2 void mcxHashSetOpts ( mcxHash* hash , double load , int option /* negative values will be ignored (feature) */ ) ; dim mcxHashMemSize ( mcxHash* hash ) ; typedef struct mcxHashSettings { dim n_buckets ; dim n_entries ; float load ; mcxbits options ; } mcxHashSettings ; void mcxHashGetSettings ( mcxHash* hash , mcxHashSettings* settings ) ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** mcxHashSearch * * action returns * * MCX_DATUM_DELETE -> deleted mcxKV* or NULL if not present * MCX_DATUM_INSERT -> new or present mcxKV* * MCX_DATUM_FIND -> mcxKV* if present NULL otherwise. * * usage: * * Values have to be inserted by the caller into the returned KV struct. * Make sure that keys point to objects that are constant * (with respect to the cmp function) during the lifetime of the hash. * YOU have to ensure the integrity of both keys and values. * This enables you to do whatever suits you, such as appending to * values. * * When inserting, check whether kv->key != key (where kv is returned value) * if this is the case, an identically comparing key is already present. * You may want to destroy one of the two keys and decide what to do * with the value. * * When deleting, the key-value pair is removed from the hash *AND RETURNED * TO CALLER* - you have to decide yourself what to do with it. You have to * fetch the val and key members of the returned mcxKV object immediately: * Subsequent inserts in the hash may reuse it. If the key was not present, * a value of NULL is returned. * * When finding, life is simple. NULL if absent, matching kv otherwise. * * note: * * memory management of keys and values is totally up to caller. * If usage is clean, you can use mcxHashFree for disposal of hash. */ #define mcxHashSearch(key, hash, ACTION) mcxHashSearchx(key, hash, ACTION, NULL) mcxKV* mcxHashSearchx ( void* key , mcxHash* hash , mcxmode ACTION , int* delta ) ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** mcxHashMerge * * this one COPIES OBJECT POINTERS and DOES NOT CLONE. * so after the merge, hash1 and hash2 keys and values should not be freed. * In case there are equivalent keys in hash1 and hash2, this may * cause trouble when the caller wants to do cleaning afterwards. * This interface is still under development. * * hashd may be equal to hash1 or hash2, and it may also be NULL. */ mcxHash* mcxHashMerge ( mcxHash* hash1 , mcxHash* hash2 , mcxHash* hashd , void* merge(void* val1, void* val2) ) ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ** mcxHashFree * * This only works if all keys are of the same type and/or all values * are of the same type, and if your objects were created as expected by * the free routines (presumably malloced heap memory) - be careful with * constant objects like constant strings. * * freekey and freeval may not free their argument. This is because * tingea does not allow routines that leave arguments in an * inconsistent state, and free routines in tingea generally accept * an argument of the form ** pptr. * In the case of mcxHashFree this means that the interface may * feel slighly more cumbersome. * A way out would have been to make the callbacks of signature * * void freemem(void** mempp) * * The caller could access *mempp, cast it to the expected type, * and later set *mempp to NULL. However, this would require * new free routines for lots of types. With the current interface * existing Release routines can be used: * * The type of free routine expected by mcxHashFree is generally * called Release or Release_v, e.g. mcxTingRelease. * Release routines release all memory of a composite object except the * memory which holds the outer struct. * * If one of key or val is *not* a composite type or is a composite type * that does not contain malloced memory, use mcxHashFreeScalar. * * Both freekey and freeval may be NULL. When NULL, the corresponding * KV member is not loooked at. This is useful e.g. when hashing objects * owned by someone else. */ void mcxHashFree ( mcxHash** hashpp , void freekey(void* keypp) /* (yourtype1** keypp) */ , void freeval(void* valpp) /* (yourtype2** valpp) */ ) ; void mcxHashFreeScalar ( void* scalar ) ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * It copies the pointers stored in the hash */ void** mcxHashKeys ( mcxHash* hash , dim* n_entries , int (*cmp)(const void*, const void*) /* works on keys */ , mcxbits opts /* unused yet */ ) ; /* Future options: SORT, SORT_DESC */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * It copies the pointers stored in the hash */ void** mcxHashKVs ( mcxHash* hash , dim* n_entries , int (*cmp)(const void*, const void*) , mcxbits opts /* unused yet */ ) ; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Prints some information to stdout. */ void mcxHashStats ( FILE* fp , mcxHash* hash ) ; typedef struct mcxHashWalk mcxHashWalk; mcxHashWalk* mcxHashWalkInit ( mcxHash *hash ) ; mcxKV* mcxHashWalkStep ( mcxHashWalk* walk , dim *i_bucket ) ; void mcxHashWalkFree ( mcxHashWalk **walkpp ) ; void mcxHashApply ( mcxHash* hash , void (*cb)(const void* key, void* val, void* data) , void* data ) ; /* UNIX ELF hash */ /* POOR! */ u32 mcxELFhash ( const void *key , u32 len ) ; /* created by Bob Jenkins */ u32 mcxBJhash ( const void* key , u32 len ) ; /* One at a time hash, Bob Jenkins/Colin Plumb */ u32 mcxOAThash ( const void *key , u32 len ) ; /* created by Daniel Phillips */ u32 mcxDPhash ( const void* key , u32 len ) ; /* "Berkely Database" hash (from Ozan Yigit's page) */ /* POOR! */ u32 mcxBDBhash ( const void *key , u32 len ) ; /* Dan Bernstein hash (from Ozan Yigit's page) */ u32 mcxDJBhash ( const void *key , u32 len ) ; /* created by Chris Torek */ u32 mcxCThash ( const void* key , u32 len ) ; /* "GNU Emacs" hash (from m4) */ /* not among the best */ u32 mcxGEhash ( const void* key , u32 len ) ; /* Fowler Noll Vo hash */ u32 mcxFNVhash ( const void *buf , u32 len ) ; /* All experimental with weak points. */ u32 mcxSvDhash ( const void *key , u32 len ) ; u32 mcxSvD2hash ( const void *key , u32 len ) ; u32 mcxSvD1hash ( const void *key , u32 len ) ; /* uses mcxDPhash */ u32 mcxStrHash ( const void* s ) ; int mcxStrCmp ( const void* a , const void* b ) ; #endif zoem-11-166/util/heap.h0000644000402500021140000000241511163174777011556 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_heap_h #define tingea_heap_h /* Use a heap to compute the K largest elements according to some sortin * criterion. * Note that a new element only has to be compared with the root (when * the heap is at full capacity) to know whether it should enter the heap * and evict the root. */ typedef struct { void *base ; dim heapSize ; dim elemSize ; int (*cmp)(const void* lft, const void* rgt) ; dim n_inserted ; } mcxHeap ; mcxHeap* mcxHeapInit ( void* heap ) ; mcxHeap* mcxHeapNew ( mcxHeap* heap , dim heapSize , dim elemSize , int (*cmp)(const void* lft, const void* rgt) ) ; void mcxHeapFree ( mcxHeap** heap ) ; void mcxHeapRelease ( void* heapv ) ; void mcxHeapClean ( mcxHeap* heap ) ; void mcxHeapInsert ( mcxHeap* heap , void* elem ) ; #endif zoem-11-166/util/let.h0000644000402500021140000000240411147245502011406 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_let #define tingea_let #include "types.h" #include "ting.h" #define TRM_FAIL 0 #define TRM_ISNUM 1 #define TRM_ISREAL 2 #define TRM_ISINF 3 #define TRM_ISNAN 4 typedef struct telRaam telRaam; telRaam* trmInit ( const char* str ) ; mcxstatus trmExit ( telRaam* raam ) ; mcxstatus trmParse ( telRaam* raam ) ; int trmEval ( telRaam* raam , long* lp , double* fp ) ; void trmRegister ( telRaam* raam , int (user_parse)(mcxTing* txt, int offset) , mcxenum (user_eval)(const char* token, long *ival, double *fval) , char user_char ) ; mcxbool trmError ( int flags ) ; mcxbool trmIsReal ( int flags ) ; mcxbool trmIsNum ( int flags ) ; mcxbool trmIsNan ( int flags ) ; mcxbool trmIsInf ( int flags ) ; void trmDump ( telRaam* raam , const char* msg ) ; void trmDebug ( void ) ; #endif zoem-11-166/util/io.h0000644000402500021140000002116611147245477011252 00000000000000/* (C) Copyright 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ /* STATUS: * usable: yes * tested: yes, stress-tested in zoem and mcl * ad hoc: somewhat * quirks: probably a few * support: limited * * AIMS * - Provide convenient and efficient wrappers for reading lines, files, searching. * - Within these wrappers, account bytes and lines read. * It is explicitly not an aim to be an all-encompassing interface, wrapping * everything provided by stdio.h. The type is not opaque and you are * encouraged to inspect its fp member. * - The open modes are inspected to infer some knowledge, * then passed on directly to fopen. * - File "-" is interpreted as either STDIN or STDOUT depending on the open mode. * * BUGS * - buffer framework is fully implemented: * mcxIOexpectNum and mcxIOexpectReal ignore buffer. * - Should incorporate more (f)error checking. * * TODO: * - document interfaces. * - document which routines corrupt the counts. * - make sure that buffer treats \0 bytes correctly. Should be * pretty close. * - buffered reads (problematic: mcxIOexpectNum and friends). * - design {reset,close} framework, esp related to usr member. * ? support for pipes */ #ifndef tingea_file_h #define tingea_file_h #include #include #include "ting.h" #include "types.h" /* The thing below seems a reasonable test for seekability. * Let's agree that the main thing is the encapsulation. * */ #define mcxFPisSeekable(fp) (!fseek(fp, 0, SEEK_CUR)) /* Possibly more stringent check: * int had_error = ferror(file); * long curpos = ftell(file); * bool seekable = (curpos != -1L && fseek(file, curpos, SEEK_SET) == 0); * if (!had_error) * clearerr(file); */ /* ************************************************************************** * * ** Implementation notes. * * * This is meant to be a lightweight layer for file operations. * It is so lightweight that the pivotal data structure is not hidden. * * Basic usage: * mcxIO* xf = mcxIOnew(somestr, "r"); * mcxIOopen(xf, EXIT_ON_FAIL); * * * Searching: * mcxIOfind(xf, pattern, ON_FAIL) * * * Reading lines: * mcxIOreadLine(xf, txt, mode) * modes (xor'ed bits): * MCX_READLINE_CHOMP * MCX_READLINE_SKIP_EMPTY * MCX_READLINE_PAR (read a paragraph) * MCX_READLINE_BSC (backslash continues line) * MCX_READLINE_DOT (single dot on single line ends paragraph) * Reading files: * mcxIOreadFile(xf, txt) * * * Reading bytes: * int c = mcxIOstep(xf) * mcxIOstepback(c, xf) * * These keep track of byte count, line count, and ofset within line. * * * Reset attributes for file name object - change name or mode. * mcxIOrenew(xf, name, mode) * * * There are some more small utility functions. * ************************************************************************** * * * * TODO: * much todo about everything. * * mcxIOdiscardLine * mcxIOskipSpace * Change to instance of sth more general. * */ #define mcxIOateof(xf) (xf->ateof) #define mcxIOstdio(xf) (xf->stdio) #define mcxIOlc(xf) ((long) ((xf->lc) + (xf->lo ? 1 : 0))) /* this also takes care of EOF * not preceded by a newline */ /* As long as you did not use mcxIOopen, feel free to do anything with the fn * member, especially right after mcxIOnew. */ typedef struct { mcxTing* fn ; char* mode ; FILE* fp ; dim lc /* line count */ ; dim lo /* line offset */ ; dim lo_ /* line offset backup, only valid when lo == 0 */ ; dim bc /* byte count */ ; int ateof ; int stdio ; mcxTing* buffer /* e.g. when tryCookie fails and unseekable stream */ ; dim buffer_consumed ; void* usr /* user object */ ; mcxstatus (*usr_reset)(void*) /* function to reset user object */ ; void (*usr_free)(void*) /* function to free user object */ ; } mcxIO ; /* * mcxIOrenew does *not* support callback for resetting the usr object */ mcxIO* mcxIOrenew ( mcxIO* xf , const char* name , const char* mode ) ; mcxIO* mcxIOnew ( const char* name , const char* mode ) ; mcxstatus mcxIOopen ( mcxIO* xf , mcxOnFail ON_FAIL ) ; mcxstatus mcxIOtestOpen ( mcxIO* xf , mcxOnFail ON_FAIL ) ; /* * mcxIOfree does *not* support callback for freeing the usr object */ void mcxIOfree ( mcxIO** xf ) ; void mcxIOfree_v ( void* xfpp ) ; void mcxIOrelease ( mcxIO* xf ) ; void mcxIOerr ( mcxIO* xf , const char *complainer , const char *complaint ) ; /* Currently, for stdin/stdout/stderr clearerr is issued if necessary. * This makes e.g. repeated reads from STDIN possible. * * usr_reset is called if present. */ mcxstatus mcxIOclose ( mcxIO *xf ) ; mcxstatus mcxIOreset ( mcxIO *xf ) ; mcxstatus mcxIOreadFile ( mcxIO *xf , mcxTing *fileTxt ) ; #define MCX_READLINE_DEFAULT 0 #define MCX_READLINE_CHOMP 1 #define MCX_READLINE_SKIP_EMPTY 2 #define MCX_READLINE_PAR 4 #define MCX_READLINE_BSC 8 #define MCX_READLINE_DOT 16 mcxstatus mcxIOreadLine ( mcxIO *xf , mcxTing *lineTxt , mcxbits flags ) ; ofs mcxIOappendChunk ( mcxIO *xf , mcxTing *dst , dim sz , mcxbits flags ) ; /* Returns the number of bytes that could be discarded. */ dim mcxIOdiscardLine ( mcxIO *xf ) ; /* Returns the number of bytes that could be discarded. * ONLY keeps the xf->bc counter up to date. */ dim mcxIOdiscard ( mcxIO *xf , dim amount ) ; /* OK to call this after mcxIOnew, before mcxIOopen */ mcxstatus mcxIOnewName ( mcxIO* xf , const char* newname ) ; /* OK to call this after mcxIOnew, before mcxIOopen */ mcxstatus mcxIOappendName ( mcxIO* xf , const char* suffix ) ; int mcxIOstep ( mcxIO* xf ) ; int mcxIOstepback ( int c , mcxIO* xf ) ; void mcxIOpos ( mcxIO* xf , FILE* channel ) ; void mcxIOlistParmodes ( void ) ; /* * Returns count of trailing characters in str not matching. */ int mcxIOexpect ( mcxIO* xf , const char* str , mcxOnFail ON_FAIL ) ; mcxstatus mcxIOexpectReal ( mcxIO* xf , double* dblp , mcxOnFail ON_FAIL ) ; mcxstatus mcxIOexpectNum ( mcxIO* xf , long* lngp , mcxOnFail ON_FAIL ) ; /* * Returns next non-white space char, * which is pushed back onto stream after reading. */ int mcxIOskipSpace ( mcxIO* xf ) ; /* * Purpose: find str in file. If str is found file pointer is set at the end * of match (fgetc or mcxIOstep would retrieve the next byte), otherwise, * the stream is at EOF. * * Internally this uses Boyer Moore Horspool (bmh) search. * It processes the stream with fgetc, so the input file need not be * seekable. This means that finding is relatively slow. * * An improvement would be to implement faster input munging for seekable * streams, (using reads of size pagesize) and then reposition the stream * after searching. * */ mcxstatus mcxIOfind ( mcxIO* xf , const char* str , mcxOnFail ON_FAIL ) ; /* * NOTE * When the cookie is not found this routine does * 1) It tries to fseek to the point of departure * 2) If that fails, it stores the bytes it could not rewind * in xfin->buffer * * + mcxIOstep * + mcxIOfind * + mcxIOskipSpace * + mcxIOexpect * + mcxIOreadLine * * will access this buffer, but certain other routines will not, e.g. * * - mcxIOreadFile * - mcxIOexpectNum * - mcxIOexpectReal * - all stdio routines (fread, fgetc) * * For all mcxIO routines this is an open bug. * */ mcxbool mcxIOtryCookie ( mcxIO* xfin , const unsigned char abcd[4] ) ; mcxbool mcxIOwriteCookie ( mcxIO* xfout , const unsigned char abcd[4] ) ; #endif zoem-11-166/util/opt.h0000644000402500021140000002073511341053226011427 00000000000000/* (C) Copyright 2002, 2003, 2004, 2005, 2006 Stijn van Dongen * (C) Copyright 2007, 2008, 2009, 2010 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ /* TODO * recode dispatch case 'no arguments supplied'. now ugly. */ #ifndef tingea_opt_h #define tingea_opt_h #include "types.h" #include "ting.h" #include "hash.h" /* ************************************************************************** * * ** Implementation notes (a few). * * This interface munges and parses text presented to it, and creates * arrays and optionally hashes from them. It does so by simply storing * pointers to the data presented to it, and does not copy anything at all. * * It is the callers job to make sure that the data scrutinized by this * interface stays constant during interface usage. * * Tentatively, this interface treats -I 3 and --I=3 as equivalent * syntax. It is possible to define -I and --I= as separate options. * (by defining -I with MCX_OPT_HASARG and --I with MCX_OPT_DEFAULT). * * TODO: * implement newline/indent magic in option descriptions. * * The prefix thing, is it necessary? caller could pass argv+prefix .. */ #define MCX_OPT_DEFAULT 0 /* -a, xyz */ #define MCX_OPT_HASARG 1 /* -a 10, xyz foo */ #define MCX_OPT_REQUIRED 2 #define MCX_OPT_INFO 4 #define MCX_OPT_HIDDEN 16 #define MCX_OPT_UNUSED 32 enum { MCX_OPT_STATUS_OK = 0 , MCX_OPT_STATUS_NOARG , MCX_OPT_STATUS_UNKNOWN , MCX_OPT_STATUS_NOMEM } ; /* struct mcxOptAnchor * * id * When using mcxOptApropos, if the option MCX_OPT_DISPLAY_SKIP is used, * an increment larger then one between successive ids (from the structs * in the array presented to mcxOptApropos) causes an additional newline * to be output before the option synopsis. * This enables the creation of paragraphs in a simple manner. * * descr_usage * By default, this just contains the description of what the option does * It is possible to specify a mark to be printed in front of that * description. This requires both the mark and the description * (which are joined in the same string) to be proceded by a special * sequence. For the mark this is "\tM" and for the description * this is "\tD". The description string should be last. A valid entry is * thus * "\tM!\tDset the resource scheme" * This will print the marker '!' inbetween the option tag and its * description. * * Presumably, the legend to such markers is explained by the caller. */ typedef struct mcxOptAnchor { char* tag /* '-foo' or '--expand-only' etc */ ; int flags /* MCX_OPT_HASARG etc */ ; int id /* ID */ ; char* descr_arg /* "" or "", NULL ok */ ; char* descr_usage /* NULL allowed */ ; } mcxOptAnchor ; void mcxOptAnchorSortByTag ( mcxOptAnchor *anchors , dim n_anchors ) ; void mcxOptAnchorSortById ( mcxOptAnchor *anchors , dim n_anchors ) ; /* * An array of these is returned by parse routines below. * An entry with .anch == NULL indicates end-of-array. */ typedef struct mcxOption { mcxOptAnchor* anch ; const char* val ; } mcxOption ; /* * these routines only use status MCX_OPT_NOARG. The interface * is not yet frozen. */ /* This tries to find as many arguments as it can, and reports the * number of array elements it skipped. */ mcxOption* mcxOptExhaust ( mcxOptAnchor* anch , char** argv , int argc , int prefix /* skip these */ , int* n_elems_read , mcxstatus* status ) ; /* This will never read past the last arguments (suffix of them). * It does currently not enforce that the number of arguments left * is exactly equal to suffix (fixme?). */ mcxOption* mcxOptParse ( mcxOptAnchor* anch , char** argv , int argc , int prefix /* skip these */ , int suffix /* skip those too */ , mcxstatus* status ) ; void mcxOptFree ( mcxOption** optpp ) ; mcxbool mcxOptIsInfo ( const char* arg , mcxOptAnchor* options ) ; #define MCX_OPT_DISPLAY_DEFAULT 0 #define MCX_OPT_DISPLAY_BREAK_HARD 1 << 4 /* break overly long lines */ #define MCX_OPT_DISPLAY_BREAK_SOFT 1 << 6 /* break overly long lines */ #define MCX_OPT_DISPLAY_CAPTION 1 << 10 /* break after option */ #define MCX_OPT_DISPLAY_PAR 1 << 12 /* ? useful ? paragraph mode */ #define MCX_OPT_DISPLAY_SKIP 1 << 14 /* display enum skips as pars */ #define MCX_OPT_DISPLAY_HIDDEN 1 << 16 /* do that */ void mcxOptApropos ( FILE* fp , const char* me /* unused currently */ , const char* syntax , int width , mcxbits display , const mcxOptAnchor opt[] ) ; /* The ones below are for spreading responsibility for parsing * argument over different modules. * See the mcl implementation for an example. */ mcxOption* mcxHOptExhaust ( mcxHash* opthash , char** argv , int argc , int prefix /* skip these */ , int* n_elems_read , mcxstatus* status ) ; mcxOption* mcxHOptParse ( mcxHash* opthash , char** argv , int argc , int prefix /* skip these */ , int suffix /* skip those too */ , mcxstatus* status ) ; /* * Creates a hash where the tag string is key, and the mcxOptAnchor is value. */ mcxHash* mcxOptHash ( mcxOptAnchor* opts , mcxHash* hash ) ; void mcxOptHashFree ( mcxHash** hashpp ) ; mcxOptAnchor* mcxOptFind ( char* tag , mcxHash* hopts ) ; void mcxUsage ( FILE* fp , const char* caller , const char** lines ) ; extern int mcxOptPrintDigits; mcxbool mcxOptCheckBounds ( const char* caller , const char* flag , unsigned char type , void* var , int (*lftRlt) (const void*, const void*) , void* lftBound , int (*rgtRlt) (const void*, const void*) , void* rgtBound ) ; /* TODO * provide escape mechanisms for delim; * e.g. mcx tilde, UNIX backslash, or SGML percent sign based. * -> smarter space-based separation. whitespace ? * * NOTE * Separates on spaces, which are replaced with '\0'. * src is modified ('\0' are written throughout). * the char* members 'char* argv[]' all point to within src. */ char** mcxOptParseString ( char* src , int* argc , unsigned char delim ) ; mcxTing* mcxOptArgLine ( const char** argv , int argc , int quote /* '[' or '"' */ ) ; /* * Severely undocumented stuff, but quite useful. * This is used to write a program that * - takes modes, e.g. 'clm dist' 'clm info' 'clm meet' * - has a set of shared options * - allows modes to have their own unique set of options * - Program and mode options are not separated by the mode, * but all are specified after the mode. * Look at htpp://micans.org/mcl/src/mcl-latest/src/shcl/clm.c * htpp://micans.org/mcl/src/mcl-latest/src/shmx/mcx.c * for two fully functioning examples. */ #define MCX_DISP_DEFAULT 0 #define MCX_DISP_HIDDEN 1 #define MCX_DISP_MANUAL 2 typedef struct { const char* name ; const char* syntax ; mcxOptAnchor* options ; int n_options ; mcxstatus (*arg_cb)(int optid, const char* val) ; mcxstatus (*init)( void ) ; mcxstatus (*main)(int argc, const char* argv[]) ; int n_at_least /* trailing arguments */ ; int n_at_most /* trailing arguments */ ; mcxbits flags ; } mcxDispHook ; typedef struct { int id ; mcxDispHook* (*get_hk)(void) ; } mcxDispEntry ; typedef struct mcx_disp_bundle { int disp_argc ; const char** disp_argv ; const char* disp_name ; const char* disp_syntax ; mcxOptAnchor* disp_shared ; dim n_disp_shared ; mcxstatus (*shared_handler)(int optid, const char* val, mcxDispHook*, struct mcx_disp_bundle*) ; void (*disp_version)(const char* me) ; mcxDispEntry* disp_table ; } mcxDispBundle ; int mcxDispatch ( mcxDispBundle* bundle ) ; #endif zoem-11-166/util/err.h0000644000402500021140000001672311137710365011426 00000000000000/* (C) Copyright 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_err_h #define tingea_err_h #include #include #include "types.h" /* Experimental scheme for logging * Contains * Three axes that have scales: * - data 1 2 3 * CELL * LIST * AGGR * - function/code 1 2 3 4 * LINE * FUNCTION * MODULE * APP * - monitoring 1 2 3 4 5 * DEBUG * INFO * WARN * ERR * PANIC * * These scales correspond with * * what (data, what are its parameters) * how (function, what is changing) * pulse (anything) * * Several axes that are radio buttons: * - IO * - Thread * - gauge progress bars * - IP inter (process) * - SLOT1 custom * - SLOT2 custom * - SLOT3 custom * * The programmer associates one or more logging levels with a logging * statement. The user sets logging levels in terms of quietness. * Quietness is quantified as shown in the list below. It may be applied * to a single axis or to several axes simultaneously. * * x is silent * 5 is tersest monitoring level * 4 is tersest function/code level * 3 is tersest data level * 9 is tersest level possible, may exceed actual upper bound * 1 is yappiest level. * * Only those statements for which the quiet level is quieter than the * user-specified level will be printed. If the programmer combines several * axes generally all the corresponding levels are checked and all have to be * OK, unless the user has specified that she is happy if at least one level is * OK. This is done by including a literal 'V' in the MCXLOGTAG string or in * the corresponding command-line option (usually -q). * * MCXLOGTAG is of the following form: * * []<[dfgimstABC][0-9]>+[V] * * The optional is one of [19x] as described above. The rest are * pairs consisting of an indicator * * d data * f function * g gauge/progress * i IO * m monitoring * n network * t thread * A custom axis 1 * B custom axis 1 * C custom axis 1 * * followed by a level. Each indicator specifies an axis; each axis has its * own scale and number of steps on the scale (see above). Finally, a 'V' * occurring anywhere signifies that OR logic is applied to loggin clauses * rather than AND logic. * * The lead tag sets a logging level for all axes simultaneously as follows: * 1 MCX_LOG_ALL * 9 MCX_LOG_TERSER * 8 MCX_LOG_TERSE * x MCX_LOG_NONE */ extern mcxbits mcxLogLevel; /* When called this one optionally checks environment variable * MCXLOGTAG to set the logging levels mcxLogLevelSetByString */ void mcxLogSetFILE ( FILE* fp , mcxbool ENV_LOG ) ; /* When writing to this file embed the print statement in an if statement * that checks whether your priority is ok with mcxLogGet. * This is paramount with GAUGE type logging as a GAUGE = x setting * may indicate that the user is logging to a shared stream. */ FILE* mcxLogGetFILE ( void ) ; extern volatile sig_atomic_t mcxLogSigGuard ; void mcxLogSig ( int sig ) ; /* ******************** data */ #define MCX_LOG_CELL 1 << 0 /* node, point, scalar */ #define MCX_LOG_LIST 1 << 1 /* list, tree, hash */ #define MCX_LOG_AGGR 1 << 2 /* everything else */ #define MCX_LOG_DATA (MCX_LOG_CELL | MCX_LOG_LIST | MCX_LOG_AGGR) #define MCX_LOG_DATA0 MCX_LOG_CELL /* ******************** function */ #define MCX_LOG_LINE 1u << 3 #define MCX_LOG_FUNCTION 1u << 4 #define MCX_LOG_MODULE 1u << 5 #define MCX_LOG_APP 1u << 6 #define MCX_LOG_FUNC (MCX_LOG_LINE | MCX_LOG_FUNCTION | MCX_LOG_MODULE | MCX_LOG_APP) #define MCX_LOG_FUNC0 MCX_LOG_LINE /* ******************** monitoring */ #define MCX_LOG_DEBUG 1u << 7 #define MCX_LOG_INFO 1u << 8 #define MCX_LOG_WARN 1u << 9 #define MCX_LOG_ERR 1u << 10 #define MCX_LOG_PANIC 1u << 11 #define MCX_LOG_MON ( MCX_LOG_DEBUG| MCX_LOG_INFO | MCX_LOG_WARN | MCX_LOG_ERR| MCX_LOG_PANIC ) #define MCX_LOG_MON0 MCX_LOG_DEBUG /* ********************* unimodal axes */ #define MCX_LOG_IO 1u << 12 #define MCX_LOG_IP 1u << 13 #define MCX_LOG_THREAD 1u << 15 #define MCX_LOG_NETWORK 1u << 16 #define MCX_LOG_ASPECTS ( MCX_LOG_IO | MCX_LOG_IP | MCX_LOG_THREAD | MCX_LOG_GAUGE | MCX_LOG_NETWORK ) /* ********************* miscellaneous*/ #define MCX_LOG_GAUGE 1u << 17 /* ********************* control */ #define MCX_LOG_AND 1u << 18 #define MCX_LOG_OR 1u << 19 #define MCX_LOG_NULL 1u << 20 /* turns of logging */ /* ********************* unspecified */ #define MCX_LOG_SLOT1 1u << 22 #define MCX_LOG_SLOT2 1u << 22 #define MCX_LOG_SLOT3 1u << 23 #define MCX_LOG_SLOT ( MCX_LOG_SLOT1 | MCX_LOG_SLOT2 | MCX_LOG_SLOT3 ) /* ********************* all / terse */ #define MCX_LOG_NONE 0 #define MCX_LOG_VERBOSE ( MCX_LOG_CELL | MCX_LOG_LINE | MCX_LOG_DEBUG | MCX_LOG_SLOT | MCX_LOG_ASPECTS ) #define MCX_LOG_TERSER ( MCX_LOG_PANIC | MCX_LOG_AGGR | MCX_LOG_APP ) #define MCX_LOG_TERSE ( MCX_LOG_TERSER | MCX_LOG_ASPECTS ) #define MCX_LOG_UNIVERSE ( MCX_LOG_DATA | MCX_LOG_FUNC | MCX_LOG_MON | MCX_LOG_SLOT | MCX_LOG_ASPECTS ) /* ********************* unused */ #define MCX_LOG_UNUSED 1u << 24 void mcxLogLevelSetByString ( const char* str ) ; void mcxLog ( mcxbits level_programmer , const char* tag , const char* fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 3, 4))) #endif ; mcxbool mcxLogGet ( mcxbits level_programmer ) ; void mcxLog2 ( const char* tag , const char* fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) #endif ; void mcxTell ( const char *caller , const char *fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) #endif ; void mcxTellf ( FILE* fp , const char *caller , const char *fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 3, 4))) #endif ; void mcxWarn ( const char *caller , const char *fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) #endif ; void mcxErr ( const char *caller , const char *fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) #endif ; void mcxErrf ( FILE* fp , const char *caller , const char *fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 3, 4))) #endif ; void mcxDie ( int status , const char *caller , const char *fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 3, 4))) #endif ; void mcxTellFile ( FILE* fp ) ; void mcxWarnFile ( FILE* fp ) ; void mcxErrorFile ( FILE* fp ) ; void mcxFail ( void ) ; void mcxExit ( int val ) ; #endif zoem-11-166/util/tok.h0000644000402500021140000000520611341063513011416 00000000000000/* (C) Copyright 2005, 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_tok #define tingea_tok #include #include "inttypes.h" #include "types.h" #include "list.h" #include "ting.h" /* This is a first sketchy attempt at some parse/tokenize routines. * The scope is not very well defined yet. Should it do basic constructs * only, or aim for more power, possibly aided by callbacks, and * god forbid, a state description? * * TODO * quoted strings not yet implemented! * SGML not yet implemented! * * unify with mcxIOExpect, possibly stuff from ding.h * wide chars? */ #define MCX_TOK_MODE_UNIX 1 /* Unix escapes, including esc newlines */ #define MCX_TOK_MODE_QUOTED 2 /* Quotes delimit tokens, hide brackets */ #define MCX_TOK_MODE_PLAIN 4 #define MCX_TOK_MODE_SGML 8 /* &code; other? */ #define MCX_TOK_DEL_WS 16 /* only delimiting whitespace */ /* Returns first character not matching fbool, NULL if none. */ char* mcxTokSkip ( const char* offset , int (*fbool)(int c) , ofs len ) ; /* * Accounts for nesting. * Will do '}', ')', ']', '>', assuming one of several conventions. */ mcxstatus mcxTokMatch ( const char* offset , char** end , mcxbits mode , ofs len /* considered if >= 0 */ ) ; /* * Find some token, skipping over expressions. * Either *pos == NULL and retval == STATUS_FAIL * or *pos != NULL and retval == STATUS_OK * or *pos != NULL and retval == STATUS_DONE */ mcxstatus mcxTokFind ( const char* offset , char* tok /* Only tok[0] considered for now! */ , char** pos , mcxbits mode , ofs len /* considered if >= 0 */ ) ; /* fixme. - document; - add free routine. - then perhaps optify. */ mcxLink* mcxTokArgs ( const char* str , long str_len , int* n_args , mcxbits opts ) ; typedef struct { mcxTing* key ; mcxLink* args ; mcxbits opts ; } mcxTokFunc ; void mcxTokFuncFree ( mcxTokFunc* tf ) ; mcxstatus mcxTokExpectFunc ( mcxTokFunc* tf , const char* str , dim str_len , char** z , int n_min , int n_max , int *n_args ) ; #endif zoem-11-166/util/ting.h0000644000402500021140000002727511253654654011612 00000000000000/* (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_ting #define tingea_ting #include "types.h" typedef struct { char *str ; dim len ; dim mxl ; } mcxTing ; /* ************************************************************************** * * ** Implementation notes (a few). * * Synopsis * This little module provides an objectified C-string compatible interface * to strings. * Some philosophy * Do not mind the overhead of 2*sizeof(int) bytes per ting. * If you have humongous amounts of small strings, use C-strings. Optionally * you can do the needed char manipulation in a ting used as scratch-space * using the ting interface, then create a normal string once you are done. * Use mcxTinguish to avoid copying if needed. * Feel free to use the str member with routines from * or perhaps from ding.h. Just remember to treat it as a const object * when doing so. * Applications * Zoem is the macro processor that processes the zoem language. It is very * string-heavy and its string operations are entirely based on the ting * module. * Caveat * Nearly all routines return a NULL pointer to indicate malloc failure. * Data structure * str: array of chars * * len: length of string in str (excluding '\0') * *(str+len) == '\0' * * mxl: current allocated number of writable char's (excluding '\0') * Allocated amount is mxl+1 * *(str+mxl) == '\0' - but don't count on that. * Notes * mcxTingEnsure is the only routine allowed to fiddle with mxl. * (apart from mcxTingInit which sets it to zero). * * Future idea * mcxTingFinalize, (realloc to length) * * Routines marked `!' will NOT accept ting==NULL argument. * Routines marked `#' should not be called other than by ting routines * * _ #Init _ * / \ * Ensure <--- #Instantiate * / \ \ * Empty !Splice New,Write,Print,PrintAfter * NWrite | * | * Append,Insert,Delete,PrintSplice * TODO * the library should be able to deal with embedded \0's. Really. */ /* ************************************************************************** * * ** Various instantiation routines. */ /* Accepts NULL argument. * void arguments so that it can be used * as callback. * * Should ordinarily *not* be used, unless * you want to initialize a ting allocated * on the frame stack. */ void* mcxTingInit ( void* ting ) ; /* Accepts NULL argument. * Should ordinarily *not* be used. */ mcxTing* mcxTingInstantiate ( mcxTing* dst_ting , const char* str ) ; /* Accepts NULL argument. Does not affect * ting->str. used for preallocing, e.g. to * prepare for successive calls of Append. (see * also Empty). */ mcxTing* mcxTingEnsure ( mcxTing* ting , dim length ) ; /* Accepts NULL argument. The string part is * set to the empty string. * Can be used for preallocing. */ mcxTing* mcxTingEmpty ( mcxTing* ting , dim length ) ; /* ************************************************************************** * * ** Some freeing routines. */ /* Free members and shell struct * You pass the address of a variable, * loosely speaking. */ void mcxTingFree ( mcxTing **tingpp ) ; /* Free members and shell struct * Use with callbacks, e.g. * for freeing hash with tings in one go. */ void mcxTingFree_v ( void *tingpp ) ; /* Free members * Use for freeing array of ting; * e.g. as callback in mcxNFree. */ void mcxTingRelease ( void *ting ) ; /* ************************************************************************** * * ** A bunch of user-land creation routines. */ /* accepts NULL argument, maps to empty string. */ mcxTing* mcxTingNew ( const char* str ) ; /* accepts NULL argument, maps to empty string. */ mcxTing* mcxTingNNew ( const char* str , dim n ) ; /* accepts NULL argument. */ mcxTing* mcxTingWrite ( mcxTing* ting , const char* str ) ; /* accepts NULL argument. */ mcxTing* mcxTingNWrite ( mcxTing* ting , const char* str , dim n ) ; /* usurps argument. */ mcxTing* mcxTingify ( char* str ) ; /* destroys argument, returns str member. */ char* mcxTinguish ( mcxTing* ting ) ; /* ************************************************************************** * * ** Appending, inserting, deleting, shrinking. * Some can be used as creation routine (e.g. append). */ #define TING_INS_CENTER -3 #define TING_INS_OVERRUN -4 #define TING_INS_OVERWRITE -5 /* * The offset argument can be negative, for subscripting from the end. * * The n_delete argument can be nonnegative, or one of * TING_INS_CENTER center, (try to) overwrite without changing length. * TING_INS_OVERRUN overwrite till the end. * TING_INS_OVERWRITE (try to) overwrite without changing length. * * The n_copy argument is not magical like the previous two. * */ /* does NOT accept NULL argument. */ mcxstatus mcxTingSplice ( mcxTing* ting , const char* pstr , ofs d_offset /* negative offset refers to end */ , ofs n_delete /* special modes as documented above */ , dim n_copy ) ; /* accepts NULL argument. */ mcxTing* mcxTingInsert ( mcxTing* ting , const char* str , ofs offset ) ; /* accepts NULL argument. */ mcxTing* mcxTingNInsert ( mcxTing* ting , const char* str , ofs offset /* of ting->str */ , dim length /* of str */ ) ; /* accepts NULL argument. */ mcxTing* mcxTingAppend ( mcxTing* ting , const char* str ) ; /* accepts NULL argument. */ mcxTing* mcxTingKAppend ( mcxTing* ting , const char* str , dim n ) ; /* accepts NULL argument. */ mcxTing* mcxTingNAppend ( mcxTing* ting , const char* str , dim n ) ; /* accepts NULL argument. */ mcxTing* mcxTingDelete ( mcxTing* ting , ofs offset , dim width ) ; /* accepts NULL argument. */ mcxTing* mcxTingShrink ( mcxTing* ting , ofs length ) ; /* Fails only for memory reason */ mcxstatus mcxTingTackc ( mcxTing* ting , unsigned char c ) ; /* Fails if last char is not the same as c */ mcxstatus mcxTingTickc ( mcxTing* ting , unsigned char c ) ; /* ************************************************************************** * * ** A bunch of printf like routines. */ /* Accepts NULL argument. */ mcxTing* mcxTingPrint ( mcxTing* ting , const char* fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) #endif ; /* Accepts NULL argument. */ mcxTing* mcxTingPrintAfter ( mcxTing* dst , const char* fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) #endif ; /* Accepts NULL argument. * same offset and delete interface as * mcxTingSplice. */ mcxTing* mcxTingPrintSplice ( mcxTing* dst , ofs offset , ofs n_delete /* count of chars to delete, special modes */ , const char* fmt , ... ) #ifdef __GNUC__ __attribute__ ((format (printf, 4, 5))) #endif ; /* ************************************************************************** * * ** Miscellaneous. */ char* mcxTingStr ( const mcxTing* ting ) ; char* mcxTingSubStr ( const mcxTing* ting , ofs offset , ofs length /* use -1 to indicate remainder of string */ ) ; /* accepts NULL argument. */ mcxTing* mcxTingRoman ( mcxTing* dst , long x , mcxbool ucase ) ; /* accepts NULL argument. */ mcxTing* mcxTingInteger ( mcxTing* dst , long x ) ; /* accepts NULL argument. */ mcxTing* mcxTingDouble ( mcxTing* dst , double x , int decimals ) ; /* ************************************************************************** * * ** Comparing. */ /* compare two mcxTing* pointers */ int mcxTingCmp ( const void* t1 , const void* t2 ) ; /* compare two mcxTing* pointers */ int mcxTingRevCmp ( const void* t1 , const void* t2 ) ; /* compare two mcxTing** pointers */ int mcxTingPCmp ( const void* t1 , const void* t2 ) ; /* compare two mcxTing** pointers */ int mcxTingPRevCmp ( const void* t1 , const void* t2 ) ; /* compare two mcxKV** pointers by key as mcxTing* */ int mcxPKeyTingCmp ( const void* k1 , const void* k2 ) ; /* compare two mcxKV** pointers by key as mcxTing* */ int mcxPKeyTingRevCmp ( const void* k1 , const void* k2 ) ; /* ************************************************************************** * * ** Hashing. */ u32 (*mcxTingHFieByName(const char* id))(const void* ting) ; u32 mcxTingELFhash ( const void* ting ) ; u32 mcxTingHash ( const void* ting ) ; u32 mcxTingBJhash ( const void* ting ) ; u32 mcxTingCThash ( const void* ting ) ; u32 mcxTingDPhash ( const void* ting ) ; u32 mcxTingBDBhash ( const void* ting ) ; u32 mcxTingGEhash ( const void* ting ) ; u32 mcxTingOAThash ( const void* ting ) ; u32 mcxTingFNVhash ( const void* ting ) ; u32 mcxTingSvDhash ( const void* ting ) ; u32 mcxTingSvD2hash ( const void* ting ) ; u32 mcxTingSvD1hash ( const void* ting ) ; u32 mcxTingDJBhash ( const void* ting ) ; #endif zoem-11-166/util/ding.h0000644000402500021140000000347411147245317011557 00000000000000/* (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_ding #define tingea_ding #include #include "types.h" #include "ting.h" char* mcxStrDup ( const char* str ) ; char* mcxStrNDup ( const char* str , dim n ) ; mcxstatus mcxStrTol ( const char* s , long* value , char** end ) ; mcxstatus mcxStrToul ( const char* s , ulong* value , char** end ) ; /* * if len < 0, strlen(p) is used. */ dim mcxStrCountChar ( const char* p , char c , ofs len /* -1 for don't know */ ) ; char* mcxStrChrIs ( const char* src , int (*fbool)(int c) , ofs len /* -1 for don't know */ ) ; char* mcxStrChrAint ( const char* src , int (*fbool)(int c) , ofs len /* -1 for don't know */ ) ; char* mcxStrRChrIs ( const char* src , int (*fbool)(int c) , ofs offset /* -1 for don't know */ ) ; char* mcxStrRChrAint ( const char* src , int (*fbool)(int c) , ofs offset /* -1 for don't know */ ) ; #define MCX_MEMPRINT_REVERSE 1 #define MCX_MEMPRINT_NOSPACE 2 /* Strides in char units, treats/truncates each unit * as/to an 8-bit entity. */ mcxTing* mcxMemPrint ( mcxTing* ting , void* p , dim n_bytes , mcxbits flags ) ; int mcxEditDistance ( const char* s1 , const char* s2 , int* lcs ) ; int mcxSetenv ( const char* kv ) ; #endif zoem-11-166/util/list.h0000644000402500021140000000641011147245506011602 00000000000000/* (C) Copyright 2004, 2005, 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_list_h #define tingea_list_h #include "gralloc.h" #include "types.h" /* TODO: * - linkDelete linkRemove semantics interface documentation. * - make prev xor next link optional. * - make hidden pointer optional. * - provide interface that uses list struct. * - convenience interface for tying two chains together. * - list-to-array interface. */ /* * History. * The data structure used is similar to that by Jan van der Steen's pool.c * code, which used to be part of this library. So kudos to Jan. The * present implementation, which is a bit different, was not directly copied * nor modified. It descended from a botched linked list implementation * having it's own buffered storage. Only at that time I realized that the * right solution for lists and hashes is to have a private pool of gridmem, * rather than deriving it from a global pool (so that we still can defer * thread-safety to malloc). Right? * The present implementation was then derived from the botched linked list * and sanitized afterwards. The linked list.c is still slightly botched. */ /* Description * This provides a doubly linked list/link interface with buffered storage * (invisible to the user). The current interface operates entirely via * links, the commanding structure is hidden. Other interface types may * arise later. * * You can create a number of chains drawing memory from the same pool. * * It only provides basic link insertions and deletions as a convenience * interface, and does not maintain consistency checks, neither on links, * nor on storage. */ typedef struct mcxLink { struct mcxLink* next ; struct mcxLink* prev ; void* val ; } mcxLink ; /* Options: * same as for mcxGrimNew */ mcxLink* mcxListSource ( dim capacity_start , mcxbits options ) ; /* * This removes all links that have the same parent link as lk. [huh?] * BEWARE freeval doesn't do anything yet */ void mcxListFree ( mcxLink** lk , void freeval(void* valpp) /* (yourtype1** valpp) */ ) ; /* Creates new chain, that can later be tied to other chains. */ mcxLink* mcxLinkSpawn ( mcxLink* lk , void* val ) ; /* * This inspects prev and next and links them if possible. * * You can use the val pointer, immediately after deleting. * That makes it unsafe in threads (but you need locking anyway). * The feature is used in the hash library. */ mcxLink* mcxLinkDelete ( mcxLink* lk ) ; /* * This just deallocates the link. */ void mcxLinkRemove ( mcxLink* lk ) ; mcxLink* mcxLinkAfter ( mcxLink* prev , void* val ) ; mcxLink* mcxLinkBefore ( mcxLink* prev , void* val ) ; void mcxLinkClose ( mcxLink* left , mcxLink* right ) ; /* * Get the grim that serves this list */ mcxGrim* mcxLinkGrim ( mcxLink* lk ) ; #endif zoem-11-166/util/gralloc.h0000644000402500021140000000167211147245457012264 00000000000000/* (C) Copyright 2004, 2005, 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_gralloc_h #define tingea_gralloc_h #include "types.h" /* * gralloc; grid memory allocation; allocation of equally sized chunks */ typedef struct mcxGrim mcxGrim; #define MCX_GRIM_GEOMETRIC 1 #define MCX_GRIM_ARITHMETIC 2 mcxGrim* mcxGrimNew ( dim sz_unit , dim n_units /* initial capacity */ , mcxbits options ) ; void* mcxGrimGet ( mcxGrim* src ) ; void mcxGrimLet ( mcxGrim* src , void* mem ) ; dim mcxGrimCount ( mcxGrim* src ) ; dim mcxGrimMemSize ( mcxGrim* src ) ; void mcxGrimFree ( mcxGrim** src ) ; #endif zoem-11-166/util/compile.h0000644000402500021140000000446411147245307012265 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_compile_h #define tingea_compile_h #ifndef TINGEA__TYPED_MINMAX # define TINGEA__TYPED_MINMAX 0 #endif #ifndef __GNUC__ # define MCX_GNUC_OK 0 # define inline /* no inline */ # define cpl__pure /* no pure */ # define cpl__const /* no const */ # define cpl__noreturn /* no noreturn */ # define cpl__malloc /* no malloc */ # define cpl__must_check /* no warn_unused_result */ # define cpl__deprecated /* no deprecated */ # define cpl__used /* no used */ # define cpl__unused /* no unused */ # define cpl__packed /* no packed */ # define likely(x) (x) # define unlikely(x) (x) #else #define MCX_GNUC_OK 1 #if __GNUC__ >= 3 # define inline __inline__ __attribute__ ((always_inline)) # define cpl__pure __attribute__ ((pure)) # define cpl__const __attribute__ ((const)) # define cpl__noreturn __attribute__ ((noreturn)) # define cpl__malloc __attribute__ ((malloc)) # define cpl__must_check __attribute__ ((warn_unused_result)) # define cpl__deprecated __attribute__ ((deprecated)) # define cpl__used __attribute__ ((used)) # define cpl__unused __attribute__ ((unused)) # define cpl__packed __attribute__ ((packed)) # define likely(x) __builtin_expect (!!(x), 1) # define unlikely(x) __builtin_expect (!!(x), 0) #else # define inline /* no inline */ # define cpl__pure /* no pure */ # define cpl__const /* no const */ # define cpl__noreturn /* no noreturn */ # define cpl__malloc /* no malloc */ # define cpl__must_check /* no warn_unused_result */ # define cpl__deprecated /* no deprecated */ # define cpl__used /* no used */ # define cpl__unused /* no unused */ # define cpl__packed /* no packed */ # define likely(x) (x) # define unlikely(x) (x) #endif #endif #endif zoem-11-166/util/getpagesize.h0000644000402500021140000000154010642147132013130 00000000000000/* Emulate getpagesize on systems that lack it. */ #ifndef HAVE_GETPAGESIZE #if !defined getpagesize && defined __BEOS__ # include # define getpagesize() B_PAGE_SIZE #endif #ifdef HAVE_UNISTD_H # include #endif #if !defined getpagesize && defined _SC_PAGESIZE # if !(defined VMS && __VMS_VER < 70000000) # define getpagesize() sysconf (_SC_PAGESIZE) # endif #endif #if !defined getpagesize && defined VMS # ifdef __ALPHA # define getpagesize() 8192 # else # define getpagesize() 512 # endif #endif #ifndef getpagesize # include # ifdef EXEC_PAGESIZE # define getpagesize() EXEC_PAGESIZE # else # ifdef NBPG # ifndef CLSIZE # define CLSIZE 1 # endif # define getpagesize() (NBPG * CLSIZE) # else # ifdef NBPC # define getpagesize() NBPC # endif # endif # endif #endif #endif /* not HAVE_GETPAGESIZE */ zoem-11-166/util/types.h0000644000402500021140000000543011147245557012002 00000000000000/* (C) Copyright 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef types_h #define types_h #include "inttypes.h" typedef unsigned long mcxbits ; typedef unsigned long mcxmode ; typedef unsigned long mcxenum ; /* mcxstatus defined below */ /* mcxbool defined below */ #define BIT_ON(var,bits) (var) |= (bits) #define BIT_OFF(var, bits) do { (var) |= (bits); (var) ^= (bits); } while (0) #define ALL_BITS_OFF 0 #define VOID_TO_UINT (unsigned) #define UINT_TO_VOID (void*) #define VOID_TO_ULONG (unsigned long) #define ULONG_TO_VOID (void*) #define NOTHING do { } while (0) /* ************************************************************************** * * ** Implementation notes (a few). * * * The intent is that routines that return mcxstatus can define their own * values, so one must check the interface of a given routine as to what kind * of symbolic values it may return. * * For example, the opt library defines MCX_OPT_OK, MCX_OPT_NOARG, and * MCX_OPT_UNKNOWN. * * The intent is also that the OK value is always defined as zero -- it's * not the zero that counts but the fact that all OK values (e.g. STATUS_OK, * MCX_OPT_OK etc) are equal. One should be able to count on this. * If multiple ok values are possible, use one of mcxenum, mcxbits, mcxmode. * */ typedef enum { STATUS_OK = 0 , STATUS_FAIL , STATUS_DONE /* for iterator type interfaces (e.g. readLine) */ , STATUS_IGNORE /* for iterator type interfaces (line parser) */ , STATUS_NOMEM , STATUS_ABORT /* e.g. user response */ , STATUS_NEW /* for cache type interfaces */ , STATUS_UNUSED /* use this as lower bound for new statuses */ } mcxstatus ; extern const char* mcx_status_list[]; #define MCXSTATUS(status) \ ( status <= STATUS_UNUSED \ ? mcx_status_list[status] \ : "NO_such_status!" \ ) #ifndef FALSE typedef enum { FALSE = 0 , TRUE = 1 } mcxbool ; #else typedef int mcxbool ; #endif typedef enum { RETURN_ON_FAIL = 1960 , EXIT_ON_FAIL , SLEEP_ON_FAIL , ENQUIRE_ON_FAIL /* user sets TINGEA_MEM_DO to e.g. exit or retry */ } mcxOnFail ; #define MCX_DATUM_THREADING 1 #define MCX_DATUM_FIND 2 #define MCX_DATUM_INSERT 4 #define MCX_DATUM_DELETE 8 #endif zoem-11-166/util/inttypes.h0000644000402500021140000000345011147245474012513 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef tingea_inttypes_h #define tingea_inttypes_h #include #include #if UINT_MAX >= 4294967295 # define MCX_UINT32 unsigned int # define MCX_INT32 int #else # define MCX_UINT32 unsigned long # define MCX_INT32 long #endif typedef MCX_UINT32 u32 ; /* at least 32 bits */ typedef MCX_INT32 i32 ; /* at least 32 bits */ typedef unsigned char u8 ; /* at least 8 bits */ #ifndef ulong # define ulong unsigned long #endif #ifndef uchar # define uchar unsigned char #endif /* dim is garantueed to be an unsigned type. * ofs is garantueed to be the corresponding signed type. */ #if 0 # define dim size_t # define ofs ssize_t #else typedef size_t dim; typedef ssize_t ofs; #endif #ifdef SIZE_MAX # define DIM_MAX SIZE_MAX #else # define DIM_MAX ((size_t)-1) #endif #ifdef SSIZE_MAX # define OFS_MAX SSIZE_MAX #else # define OFS_MAX LONG_MAX /* lame, reasonable stopgap */ #endif #ifdef SSIZE_MIN # define OFS_MIN SSIZE_MIN #else # define OFS_MIN LONG_MIN /* lame, reasonable stopgap */ #endif /* annotate 'unsigned due to prototype' * and related messages */ #define different_sign #define different_width #endif zoem-11-166/util/minmax.h0000644000402500021140000000433511147247277012133 00000000000000/* (C) Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 Stijn van Dongen * (C) Copyright 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea * under the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with tingea, in the file COPYING. */ #ifndef minmax_h #define minmax_h #include "compile.h" #if MCX_GNUC_OK && TINGEA__TYPED_MINMAX /* these buggers do not nest, which I dislike */ # define MCX_MAX(x,y) \ ( { const typeof(x) _x = x; \ const typeof(y) _y = y; \ (void) (&_x == &_y); \ _x > _y ? _x : _y; \ } ) # define MCX_MIN(x,y) \ ( { const typeof(x) _x = x; \ const typeof(y) _y = y; \ (void) (&_x == &_y); \ _x < _y ? _x : _y; \ } ) #else /* The usual brain-damaged min and max, which do nest though. */ # define MCX_MAX(a,b) ((a)>(b) ? (a) : (b)) # define MCX_MIN(a,b) ((a)<(b) ? (a) : (b)) #endif #define ABS(x) ((x) > 0 ? (x) : (x) < 0 ? (-(x)) : 0) /* The first version cannot be used recursively. * I don't like this at all I think, which is why I turned it off. */ #if 0 && MCX_GNUC_OK # define MCX_SIGN(a) \ __extension__ \ ( { typedef _ta = (a) \ ; _ta _a = (a) \ ; _a > 0 \ ? 1 \ : _a < 0 \ ? -1 \ : 0 \ ; } \ ) #else # define MCX_SIGN(a) \ ((a) > 0 ? 1 : !(a) ? 0 : -1) #endif #define MCX_RESTRICT(x,a,b) \ do { if (x < a) x = a; else if (x > b) x = b; } while (0) #endif zoem-11-166/util/tr.h0000644000402500021140000001037311147245551011257 00000000000000/* (C) Copyright 2005, 2006, 2007, 2008, 2009 Stijn van Dongen * * This file is part of tingea. You can redistribute and/or modify tingea under * the terms of the GNU General Public License; either version 3 of the License * or (at your option) any later version. You should have received a copy of * the GPL along with tingea, in the file COPYING. */ #ifndef tingea_tr #define tingea_tr #include #include "ting.h" #include "types.h" #include "inttypes.h" /* * README * This interface is not POSIX compliant. It might evolve to * optionally be indeed. * However, given some of the braindeadliness of POSIX tr compliance, * I don't think the worlds needs another tr implementation. * My gripe is mainly about derailed syntax such as '[:alpha:0'. * It should go down in a ball of flames, not happily parse. * To be honest, I don't know for sure whether this is a POSIX * lack of requirement or an implementation choice. * * I did choose to follow most of the POSIX syntax. It is probably * a sign of weakness. * This interface should be able to do everything a POSIX interface can, * possibly more. * * - It allows separate specification of src, dst, del and squash sets. * - Provisionally we accept "^spec" to indicate complement, * for any of src dst del squash sets. * - It uses [*c*20] to denote repeats, rather than [c*20]. * rationale: do not slam door shut on new syntax. * - It does not recognize '[a-z]' ranges, only 'a-z'. * rationale: none. If ever, notation will be [-a-z] or similar. * - The magic repeat operator [*c#] stops on boundaries * rationale: I like it. * A boundary is introduced by stop/start of ranges and classes. * - The magic repeat operator [*c*] does not stop on boundaries. * - For now, the interface does 1) deletion, 2) translation, 3) squashing. * in the future it may provide a custom order of doing things. * * * Apart from the fact that you cannot have '\0' in C strings, everything * here should work for '\0' as well - specifically the mcxTrTable structure. * However, the current interface uses C strings for dst and src and C strings * for data. * * More documentation to follow. * */ extern const char* mcx_tr_err; extern mcxbool mcx_tr_debug; typedef struct { u32 tlt[256] ; mcxbits modes ; } mcxTR ; #define MCX_TR_DEFAULT 0 #define MCX_TR_TRANSLATE 1 << 1 #define MCX_TR_SOURCE 1 << 2 #define MCX_TR_DEST 1 << 3 #define MCX_TR_SQUASH 1 << 4 #define MCX_TR_DELETE 1 << 5 #define MCX_TR_SOURCE_C 1 << 6 #define MCX_TR_DEST_C 1 << 7 #define MCX_TR_DELETE_C 1 << 8 #define MCX_TR_SQUASH_C 1 << 9 #define MCX_TR_COMPLEMENT 1 << 10 mcxstatus mcxTRloadTable ( mcxTR* tr , const char* src , const char* dst , const char* set_delete , const char* set_squash , mcxbits modes ) ; /* returns new length of string. * fixme: document map/squash semantics. */ ofs mcxTRtranslate ( char* src , mcxTR* tr ) ; ofs mcxTingTranslate ( mcxTing* src , mcxTR* tr ) ; ofs mcxTingTr ( mcxTing* txt , const char* src , const char* dst , const char* set_delete , const char* set_squash , mcxbits flags ) ; /* Accepts e.g. \012 and sets *value to 10. * idem \xa0 and \n (\t, \r, \b etc) * Does *not* yet accept \0xa0 * * Returns next parsable character. * * This interface should be moved to ding. */ char* mcxStrEscapedValue ( const char* p , const char* z , int *value ) ; /* * returns a ting containing all the characters according to bits. * bits accept * MCX_TR_SOURCE * MCX_TR_SOURCE_C * MCX_TR_SQUASH * MCX_TR_SQUASH_C * MCX_TR_DELETE * MCX_TR_DELETE_C * * NOTE * MCX_TR_DEST * MCX_TR_DEST_C * are not yet implemented. * * NOTE DANGER SIGN * tr no longer contains information on complements that were * used in constructing it. * The complements that bits refer to is simply the information * present in tr. * So a source of "^a-z" given to mcxTRloadTable * and MCX_TR_SOURCE_C given to mcxTRsplash * result in a string containing all of a-z. */ mcxTing* mcxTRsplash ( mcxTR* tr , mcxbits bits ) ; #endif zoem-11-166/src/0000777000402500021140000000000011576212301010344 500000000000000zoem-11-166/src/Makefile.am0000644000402500021140000000115711444403123012316 00000000000000# $Id: Makefile.am,v 1.21 2006-02-14 15:50:07 flux Exp $ INCLUDES = -I$(top_srcdir) ## noinst_PROGRAMS = zoem bin_PROGRAMS = zoem zoem_SOURCES = ops-grape.c ops-xtag.c op-inspect.c op-format.c \ ops-env.c ops-constant.c curly.c digest.c entry.c \ iface.c source.c sink.c filter.c key.c dict.c ops.c parse.c read.c \ segment.c util.c zoem.c version.c zoem_LDFLAGS = -lm LDADD = ../util/libutil.a EXTRA_DIST = curly.h digest.h entry.h parse.h segment.h key.h dict.h \ source.h sink.h read.h util.h filter.h iface.h zlimits.h version.h \ ops.h ops-xtag.h ops-grape.h ops-env.h ops-constant.h \ op-inspect.h op-format.h zoem-11-166/src/Makefile.in0000644000402500021140000004030611576203400012330 00000000000000# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ # $Id: Makefile.am,v 1.21 2006-02-14 15:50:07 flux Exp $ VPATH = @srcdir@ 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 = : bin_PROGRAMS = zoem$(EXEEXT) subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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 = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am_zoem_OBJECTS = ops-grape.$(OBJEXT) ops-xtag.$(OBJEXT) \ op-inspect.$(OBJEXT) op-format.$(OBJEXT) ops-env.$(OBJEXT) \ ops-constant.$(OBJEXT) curly.$(OBJEXT) digest.$(OBJEXT) \ entry.$(OBJEXT) iface.$(OBJEXT) source.$(OBJEXT) \ sink.$(OBJEXT) filter.$(OBJEXT) key.$(OBJEXT) dict.$(OBJEXT) \ ops.$(OBJEXT) parse.$(OBJEXT) read.$(OBJEXT) segment.$(OBJEXT) \ util.$(OBJEXT) zoem.$(OBJEXT) version.$(OBJEXT) zoem_OBJECTS = $(am_zoem_OBJECTS) zoem_LDADD = $(LDADD) zoem_DEPENDENCIES = ../util/libutil.a zoem_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(zoem_LDFLAGS) $(LDFLAGS) \ -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(zoem_SOURCES) DIST_SOURCES = $(zoem_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_cv_use_includepath = @ac_cv_use_includepath@ 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_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = -I$(top_srcdir) zoem_SOURCES = ops-grape.c ops-xtag.c op-inspect.c op-format.c \ ops-env.c ops-constant.c curly.c digest.c entry.c \ iface.c source.c sink.c filter.c key.c dict.c ops.c parse.c read.c \ segment.c util.c zoem.c version.c zoem_LDFLAGS = -lm LDADD = ../util/libutil.a EXTRA_DIST = curly.h digest.h entry.h parse.h segment.h key.h dict.h \ source.h sink.h read.h util.h filter.h iface.h zlimits.h version.h \ ops.h ops-xtag.h ops-grape.h ops-env.h ops-constant.h \ op-inspect.h op-format.h all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ 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; \ else { print "f", $$3 "/" $$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_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) zoem$(EXEEXT): $(zoem_OBJECTS) $(zoem_DEPENDENCIES) @rm -f zoem$(EXEEXT) $(zoem_LINK) $(zoem_OBJECTS) $(zoem_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/curly.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dict.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/digest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/entry.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iface.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-format.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-inspect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops-constant.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops-env.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops-grape.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops-xtag.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ops.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/segment.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sink.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/source.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/version.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zoem.Po@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) '$<'` 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: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ 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: $(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" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 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 check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags 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-binPROGRAMS 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 -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ clean-generic ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ 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-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-binPROGRAMS # 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: zoem-11-166/src/ops-grape.c0000644000402500021140000002203610651104050012316 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include #include #include #include "ops-grape.h" #include "util.h" #include "parse.h" #include "util/ting.h" #include "util/hash.h" #include "util/alloc.h" #include "util/types.h" #include "util/compile.h" static const char* spaces = " "; /* must be 75 spaces */ /* ahem, design: * all the keys in a tbl are mcxTings. * all the vals in a tbl are dnodes. * all user values are stored in dnode->dat. */ typedef struct dnode { mcxTing* dat ; mcxHash* tbl ; } dnode ; /* data node */ /* (how) can I do this in one step? */ static dnode dn__ = { NULL, NULL } ; static dnode* dnode_g = &dn__ ; static dnode* dnode_new ( const char* str , int n ) { dnode* dn = mcxAlloc(sizeof(dnode), EXIT_ON_FAIL) ; dn->dat = str ? mcxTingNew(str) : NULL ; dn->tbl = n ? yamHashNew(4) : NULL ; return dn ; } static void dnode_free ( void* dnodepp ) { dnode* dn = *((dnode**) dnodepp) ; if (dn) mcxFree(dn) ; } /* * if slot exists, remove everything attached to key slot in dn->tbl. * otherwise, empty tbl and dat members in dn, * leave dn in consistent state. */ static mcxbool dnode_cut ( dnode* dn , mcxTing* slot ) { if (!dn) return FALSE ; if (slot && !dn->tbl) return FALSE ; else if (slot) { mcxKV* kv = mcxHashSearch(slot, dn->tbl, MCX_DATUM_DELETE) ; dnode* dnx = kv ? (dnode*) kv->val : NULL ; mcxbool ok = kv ? dnode_cut(dnx, NULL) : FALSE ; mcxTing* txt= kv ? (mcxTing*) kv->key : NULL ; mcxTingFree(&txt) ; dnode_free(&dnx) ; return ok ; } else { mcxbool ok = TRUE ; if (dn->dat) { mcxTingFree(&(dn->dat)) ; } if (dn->tbl) { mcxHashWalk* walk = mcxHashWalkInit(dn->tbl) ; dim i_bucket ; mcxKV* kv ; while((kv = mcxHashWalkStep(walk, &i_bucket))) { dnode* dnx = (dnode*) kv->val ; ok = ok && dnode_cut(dnx, NULL) ; } mcxHashFree(&(dn->tbl), mcxTingRelease, mcxHashFreeScalar) ; mcxHashWalkFree(&walk) ; } /* these two actions leave dnx->tbl in consistent state so that * calling dnode_cut can either issue a mcxHashFree (in this branch, * the !slot case) on the table in which dnx is a value, * or it can just remove the key-value pair in which dnx is the * value (in the slot! branch). */ return ok ; } return TRUE /* unreachcode */ ; } void dnodePrint ( dnode* dn , int level ) ; mcxstatus yamDataSet ( const char* str , mcxbits bits , mcxbool *overwrite , mcxbool cond ) { mcxTing* val = mcxTingNew(str) ; mcxbool warn = bits & YAM_SET_WARN ; mcxbool unary = bits & YAM_SET_UNARY ; int i ; dnode* dn = dnode_g ; mcxTing* key = mcxTingEmpty(NULL, 10) ; mcxbool scopes = !unary && seescope(val->str, val->len) >= 0 ? TRUE : FALSE ; mcxbool newleaf = TRUE ; for (i=1;i<=n_args_g;i++) { mcxKV* kv ; if (!dn->tbl) dn->tbl = yamHashNew(4) ; mcxTingWrite(key, key_and_args_g[i].str) ; kv = mcxHashSearch ( key , dn->tbl , MCX_DATUM_INSERT ) ; if (kv->key == key) /* autovivification, key must now be renewed */ { key = mcxTingEmpty(NULL, 10) ; kv->val = dnode_new(NULL, 0) ; newleaf = TRUE ; } else newleaf = FALSE ; dn = (dnode*) kv->val ; } if (scopes) { yamSeg* tmpseg = yamStackPushTmp(val) ; int x ; int ct = 0 ; if (!dn->tbl) dn->tbl = yamHashNew(4) ; while ((x = yamParseScopes(tmpseg, 2, 0)) == 2) { mcxTing* lkey = mcxTingNew(arg1_g->str) ; mcxKV* kv = mcxHashSearch(lkey, dn->tbl, MCX_DATUM_INSERT) ; ct += x ; if (kv->key == lkey) kv->val = dnode_new(arg2_g->str, 0) ; else { mcxTingFree(&lkey) ; if (!cond) { mcxTingWrite(((dnode*) kv->val)->dat, arg2_g->str) ; if (overwrite) *overwrite = TRUE ; if (warn) mcxErr ( "data" , "overwriting key/val <%s>/<%s>" , ((mcxTing*) kv->key)->str , arg2_g->str ) ; } } } ct += x ; yamStackFreeTmp(&tmpseg) ; mcxTingFree(&val) ; if (ct == 1) { if (!dn->dat) dn->dat = mcxTingNew(arg1_g->str) ; else if (!cond) mcxTingWrite(dn->dat, arg1_g->str) ; } else if (x == 1) yamErr ( "\\dset#2" , "ignoring trailing value <%s>" , arg1_g->str ) ; } else { if (!dn->dat) dn->dat = val ; else if (!cond) { mcxTingWrite(dn->dat, val->str) ; if (overwrite) *overwrite = TRUE ; if (warn) mcxErr ( "data" , "overwriting key/val <%s>/<%s>" , key->str , val->str ) ; mcxTingFree(&val) ; } } mcxTingFree(&key) ; return STATUS_OK ; } const char* yamDataGet ( void ) { int i ; dnode* dn = dnode_g ; mcxTing* key = mcxTingEmpty(NULL, 10) ; for (i=1;i<=n_args_g;i++) { mcxKV* kv ; if (!dn || !dn->tbl) { mcxTingFree(&key) ; return NULL ; } mcxTingWrite(key, key_and_args_g[i].str) ; kv = mcxHashSearch ( key , dn->tbl , MCX_DATUM_FIND ) ; if (!kv) { mcxTingFree(&key) ; return NULL ; } dn = (dnode*) kv->val ; } mcxTingFree(&key) ; return dn->dat ? dn->dat->str : NULL ; } mcxstatus yamDataFree ( void ) { int i ; dnode* dn = dnode_g ; mcxTing* key = mcxTingEmpty(NULL, 10) ; mcxTing* slot = NULL ; mcxbool ok = TRUE ; for (i=1;itbl) { mcxTingFree(&key) ; return STATUS_FAIL ; } mcxTingWrite(key, key_and_args_g[i].str) ; kv = mcxHashSearch ( key , dn->tbl , MCX_DATUM_FIND ) ; if (!kv) { mcxTingFree(&key) ; return STATUS_FAIL ; } dn = (dnode*) kv->val ; } if (n_args_g) slot = mcxTingNew(key_and_args_g[n_args_g].str) ; else slot = NULL ; ok = dnode_cut(dn, slot) ; mcxTingFree(&key) ; mcxTingFree(&slot) ; return ok ? STATUS_OK : STATUS_FAIL ; } mcxstatus yamDataPrint ( void ) { int i ; dnode* dn = dnode_g ; mcxTing* key = mcxTingEmpty(NULL, 10) ; fprintf(stdout, "# printing node ") ; for (i=1;i<=n_args_g;i++) { mcxKV* kv ; if (!dn || !dn->tbl) { mcxTingFree(&key) ; return STATUS_FAIL ; } mcxTingWrite(key, key_and_args_g[i].str) ; fprintf(stdout, "<%s>", key->str) ; kv = mcxHashSearch ( key , dn->tbl , MCX_DATUM_FIND ) ; if (!kv) { mcxTingFree(&key) ; return STATUS_FAIL ; } dn = (dnode*) kv->val ; } fprintf(stdout, "\n") ; dnodePrint(dn, n_args_g) ; fprintf(stdout, "# done printing data\n") ; mcxTingFree(&key) ; return STATUS_OK ; } void dnodePrint ( dnode* dn , int level ) { if (level > 74) { fprintf(stdout, "%s....\n", spaces) ; return ; } if (dn->dat) { fprintf(stdout, "%s", spaces+(75-level)) ; fprintf(stdout, "|<%s>\n", dn->dat->str) ; } ; if (dn->tbl) { mcxHashWalk *walk = mcxHashWalkInit(dn->tbl) ; mcxKV* kv ; dim i_bucket ; while((kv = mcxHashWalkStep(walk, &i_bucket))) { fprintf(stdout, "%s", spaces+(75-level-1)) ; fprintf(stdout, "*<%s>\n", ((mcxTing*) kv->key)->str) ; dnodePrint((dnode*) kv->val, level+1) ; } mcxHashWalkFree(&walk) ; } return ; } /* fixme: ugly use of n_args_g in here. */ void mod_grape_exit ( void ) { n_args_g = 0 ; yamDataFree() ; } void mod_grape_init ( void ) { ; } zoem-11-166/src/ops-xtag.c0000644000402500021140000001103311256505107012170 00000000000000/* (C) Copyright 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include "ops-xtag.h" #include #include "util.h" #include "segment.h" #include "digest.h" #include "util/types.h" #include "util/ding.h" #include "util/list.h" yamSeg* yamXtag ( yamSeg* seg , mcxTing* dev /* if dev->len == 0, implicit closing tag */ , mcxTing* arg ) { mcxTing* txt = mcxTingEmpty(NULL, 80) ; char* me = arg ? "\\<>#2" : "\\<>#1" ; mcxbool ok = TRUE ; mcxbits flags = 0 ; lblStack* xmlStack = sinkGetXML() ; sink* sk = sinkGet() /* docme: is this (default) sink the one we want? */ ; if (yamDigest(dev,dev, seg)) ok = FALSE ; if (ok && arg && yamDigest(arg, arg, seg)) ok = FALSE ; if (!ok) NOTHING /* we interpret, but keep syntax as is, so that the thing * will pass again through this routine in OUTPUT mode. * Why? because otherwise everything is stuffed in \@{<..>} scope * (and invisible to (repeated) interpretation). * Perhaps it'd be better to stuff it in \@{<} .. \@{>} scope. */ ; else if (seg->flags & SEGMENT_DIGEST) { if (arg) mcxTingPrint(txt, "\\<%s>{%s}", dev->str, arg->str) ; else mcxTingPrint(txt, "\\<%s>", dev->str) ; flags |= SEGMENT_CONSTANT ; } else while(1) { ok = FALSE /* if branch: close tag, either explicit or implicit */ ; if (*(dev->str) == '/' || !dev->len) { const char* otag = NULL ; if (arg) { yamErr(me, "No arguments allowed with closing tag") ; break ; } if (!(otag = ting_stack_pop(xmlStack))) { yamErr ( me , "XML syntactic sugar stack underflow at file <%s> tag " , sk->fname , dev->len ? dev->str+1 : "" ) ; break ; } if (dev->len && strcmp(dev->str+1, otag)) { yamErr(me, "tag closes <%s>", dev->str+1, otag) ; break ; } mcxTingPrint(txt, "\\@{\\X\\N\\J\\N}", otag) ; } /* open tag. * recognize and leave it alone. * recognize <$....> and then ignore dollar. */ else { char* p = mcxStrChrIs(dev->str, isspace, -1) ; unsigned char z = *(dev->str+dev->len-1) ; mcxbool closing = dev->str[0] == '!' || dev->str[0] == '*' || dev->str[0] == '?' || z == '/' ; unsigned delta = dev->str[0] == '*' ; mcxbool opening = !arg && !closing ; int taglen = (p ? (unsigned) (p - dev->str) : dev->len) - delta /* ends at white space */ ; int devlen = dev->len - delta /* used in printf length specification, hence int */ ; if (z == '!') /* this makes \ work */ devlen -= 1 , yamErr(me, "<...!> syntax now deprecated") ; if (closing && arg) { yamErr(me, "no args allowed with closing syntax <%s>", dev->str) ; break ; } if (opening) ting_stack_push(xmlStack, dev->str+delta, taglen) /* fixme check (alloc) error */ ; txt = arg ? mcxTingPrint ( txt , "\\@{<%s>}%s\\@{}" , dev->str+delta , arg->str , taglen , dev->str+delta ) : opening ? mcxTingPrint ( txt , "\\@{\\X\\N<%.*s>\\N\\I}" , devlen , dev->str+delta ) : mcxTingPrint ( txt , "\\@{<%.*s>}" , devlen , dev->str+delta ) ; } ok = TRUE ; break ; } seg_check_ok(ok, seg) ; mcxTingFree(&dev) ; mcxTingFree(&arg) ; return yamSegPushx(seg, txt, flags) ; } void mod_xtag_exit ( void ) { ; } void mod_xtag_init ( void ) { ; } zoem-11-166/src/op-inspect.c0000644000402500021140000002454010722546263012523 00000000000000/* (C) Copyright 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of zoem. You can redistribute and/or modify zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with zoem, in the file COPYING. */ /* TODO * should with lines return value follow input convention * about presence/absence of last newline? */ #include "op-inspect.h" #include #include #include #include "util.h" #include "digest.h" #include "key.h" #include "curly.h" #include "segment.h" #include "read.h" #include "parse.h" #include "iface.h" #include "util/ting.h" #include "util/ding.h" #include "util/err.h" #include "util/list.h" #define MATCH_MAX 10 #define REX_KNMP 1 #define REX_INTERPOLATE 2 #define REX_MATCH_ONCE 4 #define ISP_DISCARD_NIL_OUT 32 #define ISP_DISCARD_MISS 64 #define ISP_RETURN_BOOL 128 struct inspect_dir { regex_t reg ; regmatch_t matches[MATCH_MAX] ; mcxTing* data ; mcxTing* result ; dim offset ; int n_args ; int n_hits ; mcxbits opts ; } ; mcxstatus do_rex ( struct inspect_dir* dir , yamSeg* seg ) { regex_t* reg = &dir->reg ; regmatch_t *matches = dir->matches ; mcxTing* data = dir->data ; dim offset = dir->offset ; mcxbits opts = dir->opts ; mcxTing* result = dir->result ; int match_so, match_eo, match_len, n_hits = 0 ; mcxbool match ; mcxbool status = STATUS_FAIL ; mcxbool interpolate = opts & REX_INTERPOLATE ; mcxbool knmp = opts & REX_KNMP ; int i ; const char* me = "\\inspect#4" ; char* A, *Z, *p ; dir->n_hits = 0 ; A = data->str ; Z = data->str + data->len ; p = A ; while (offset < data->len) { status = regexec(reg, data->str+offset, MATCH_MAX, dir->matches, 0) ; p = data->str+offset ; match = !status ; match_so = match ? matches[0].rm_so : -1 ; match_eo = match ? matches[0].rm_eo : -1 ; match_len = match_eo - match_so /* if no match, possibly output final nmp */ /* ignore if !n_hits */ ; if (!match && knmp) mcxTingAppend(result, p) ; else if (match) { n_hits++ ; if (knmp) mcxTingNAppend(result, p, match_so) ; if (interpolate) { yamSeg* rowseg = NULL ; for (i=1;i<=dir->n_args;i++) { if (matches[i].rm_so < 0) mcxWarn(me, "no atom <%d>", i) , mcxTingEmpty(key_and_args_g+i+1, 0) ; else mcxTingNWrite ( key_and_args_g+i+1 , p+matches[i].rm_so , matches[i].rm_eo - matches[i].rm_so ) ; } if ((rowseg = yamExpandKey(seg, KEY_ANON))) mcxTingAppend(result,rowseg->txt->str) , yamSegFree(&rowseg) ; else mcxErr(me, "unexpected setback") ; } else mcxTingAppend(result, key_g->str) ; } if (match) { if (opts & REX_MATCH_ONCE) { if (knmp) mcxTingAppend(result, data->str + offset + match_eo) ; offset = data->len ; } else if (match_len) offset += match_eo ; else { offset += match_eo + 1 ; if ((*p+match_so) && knmp) mcxTingNAppend(result, p+match_so, 1) ; } } else offset = data->len ; } dir->n_hits = n_hits ; return STATUS_OK ; } int chunk_it_up ( mcxLink* lk , mcxTing* data , mcxbits piecewise ) { int ct = 0, x = 0 ; if (!piecewise) { mcxTing* tg = mcxTingNew(data->str) ; mcxLinkAfter(lk, tg) ; return 1 ; } else if (piecewise & 1) /* arg-wise */ { yamSeg* tmpseg = yamStackPushTmp(data) ; while (1 == (x = yamParseScopes(tmpseg, 1, 0))) { mcxTing* tg = mcxTingNew(key_and_args_g[1].str) ; lk = mcxLinkAfter(lk, tg) ; ct++ ; } yamStackFreeTmp(&tmpseg) ; } else if (piecewise & 2) { const char* s = data->str, *t = NULL ; while ((t = strchr(s, '\n'))) { mcxTing* tg = mcxTingNNew(s, t-s) ; lk = mcxLinkAfter(lk, tg) ; ct++ ; s = t+1 ; } if (*s) /* last line not newline separated */ { mcxTing* tg = mcxTingNew(s) ; lk = mcxLinkAfter(lk, tg) ; ct++ ; } } return ct ; } /* POSIX regex metachars are ^.[$()|*+?{\ */ yamSeg* yamInspect4 ( yamSeg* seg ) { mcxTing* mods = mcxTingNew(arg1_g->str) ; mcxTing* pat = mcxTingNew(arg2_g->str) ; mcxTing* sub = mcxTingNew(arg3_g->str) ; mcxTing* data = mcxTingNew(arg4_g->str) ; mcxTing* result = mcxTingEmpty(NULL, data->len) ; mcxbits piecewise = 0 /* 1=vargwise 2=linewise */ ; mcxbits opts = REX_KNMP ; mcxbool ok = FALSE ; mcxbool esc_slash = FALSE /* NOT USED */ ; yamSeg* modseg = NULL ; mcxLink* args = mcxListSource(20, MCX_GRIM_ARITHMETIC) ; mcxLink* arg = NULL ; const char* me = "\\inspect#4" ; mcxbool reg_ok = FALSE ; int n_args = 0, rc, k = 0, x = 0 ; struct inspect_dir dir ; int regflags = REG_EXTENDED /* fixme: single point of failure */ ; dir.result = mcxTingEmpty(NULL, 80) ; dir.data = mcxTingEmpty(NULL, 80) ; while (1) { if ( yamDigest(mods, mods, seg) || yamDigest(data, data, seg) || yamDigest(mods, mods, seg) || yamDigest(pat, pat, seg) || yamDigest(sub,sub, seg) ) break ; modseg = yamStackPushTmp(mods) ; while (2 == (x = yamParseScopes(modseg, 2, 0))) { const char* val = arg2_g->str /* danger arg2_g */ ; if (strcmp(arg1_g->str, "mods")) continue ; if (strstr(val, "icase")) regflags |= REG_ICASE ; if (!strstr(val, "dotall")) regflags |= REG_NEWLINE ; if (strstr(val, "iter-lines")) piecewise = 2 ; if (strstr(val, "iter-args")) piecewise = 1 ; if (strstr(val, "discard-nmp")) opts ^= REX_KNMP ; if (strstr(val, "discard-nil-out")) opts |= ISP_DISCARD_NIL_OUT ; if (strstr(val, "discard-miss")) opts |= ISP_DISCARD_MISS ; if (strstr(val, "count-matches")) opts |= ISP_RETURN_BOOL ; if (strstr(val, "unprotect-slash")) esc_slash = TRUE ; if (strstr(val, "match-once")) opts |= REX_MATCH_ONCE ; } if (x < 0) break ; if ((n_args = chunk_it_up(args, data, piecewise) < 0)) break ; ting_tilde_expand(pat, YAM_TILDE_UNIX | YAM_TILDE_REGEX) ; if (tracing_g & ZOEM_TRACE_REGEX) mcxTellf(stdout, me, "using regex <%s>", pat->str) # if 0 /* debug section */ ; { mcxLink* lk = args->next ; while (lk) { mcxTing* tg = lk->val ; lk = lk->next ; } } # endif ; if (regcomp(&dir.reg, pat->str, regflags)) { yamErr(me, "regex <%s> did not compile", pat->str) ; break ; } else reg_ok = TRUE ; if ( !strncmp(sub->str, "_#", 2) && isdigit((unsigned char) sub->str[2]) ) { opts |= REX_INTERPOLATE ; k = (unsigned char) *(sub->str+2) - '0' ; rc = yamClosingCurly(sub, 3, NULL, RETURN_ON_FAIL) ; if (rc < 0) { yamErr(me, "unexpected error in anonymous sub part") ; break ; } else if (k > 9 || rc+4 != sub->len) { yamErr(me, "anonymous sub <%s> not ok", sub->str) ; break ; } mcxTingNWrite(key_g, sub->str, 3) ; n_args_g = k+1 ; mcxTingNWrite(arg1_g, sub->str+4, rc-1) ; } else mcxTingWrite(key_g, sub->str) ; mcxTingFree(&mods) ; mcxTingFree(&pat) /* ******************************************************************* */ /* so far so good, let's rumble */ /* ******************************************************************* */ ; dir.opts = opts ; dir.n_args = k ; arg = args->next ; while (arg) { mcxstatus status ; mcxTing* tg = arg->val ; if (!tg) mcxDie(1, me, "ka-ching") ; mcxTingWrite(dir.data, ((mcxTing*) arg->val)->str) ; dir.offset = 0 ; dir.n_hits = 0 ; if ((status = do_rex(&dir, seg))) { mcxErr(me, "regex failed") ; break ; } if (opts & ISP_RETURN_BOOL) mcxTingInteger(dir.result, dir.n_hits) ; if (!dir.n_hits && opts & ISP_DISCARD_MISS) NOTHING ; else if (!dir.result->len && opts & ISP_DISCARD_NIL_OUT) NOTHING ; else if (piecewise & 1) mcxTingPrintAfter(result, "{%s}", dir.result->str) ; else if (piecewise & 2) mcxTingPrintAfter(result, "%s\n", dir.result->str) ; else mcxTingAppend(result, dir.result->str) ; mcxTingEmpty(dir.result, 0) ; arg = arg->next ; } if (!arg) ok = TRUE ; break ; } seg_check_ok(ok, seg) ; { mcxLink* lk = args->next ; mcxTingFree(&data) ; mcxTingFree(&mods) ; mcxTingFree(&pat) ; mcxTingFree(&sub) ; mcxTingFree(&dir.result) ; mcxTingFree(&dir.data) ; if (reg_ok) regfree(&dir.reg) ; while (lk) { mcxTingFree((mcxTing**) &(lk->val)) /* dirty */ ; lk = lk->next ; } mcxListFree(&args, mcxTingFree_v) ; } return yamSegPush(seg, result) ; } zoem-11-166/src/op-format.c0000644000402500021140000004126711065671031012344 00000000000000/* (C) Copyright 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ /* TODO * remove idiotic justify shift twitch */ #include "op-format.h" #include #include #include #include "util.h" #include "digest.h" #include "key.h" #include "curly.h" #include "segment.h" #include "read.h" #include "parse.h" #include "iface.h" #include "util/alloc.h" #include "util/ting.h" #include "util/ding.h" #include "util/err.h" /* TODO * * sth to specify no padding at right side for centered * and substring alignment. (to remove trailing spaces) * * for padding, apply length key - tricky with truncation. */ long includein ( long num , long lft , long rgt ) { if (num < lft) return lft ; if (num > rgt) return rgt ; return num ; } enum { PADPATTERN = 0 , DELIMLEFT , DELIMRIGHT , ATPIVOT , ATNUM , LENKEY , LENARG , SUBS , BORDERLEFT , BORDERRIGHT , N_FORMAT_PARAMS /* this provides interface for loads of directives */ } ; enum { SUB_ARG = 0 , SUB_DELIMLEFT , SUB_DELIMRIGHT , N_FORMAT_SUBS /* interface for arguments to {subs} directive */ } ; #define parlen(x) (par+x)->len #define parstr(x) (par+x)->str #define thepar(x) (par+x) /* we pass/name par across multiple routines, beware */ #define thesub(x) (sub+x) static int ptp /* a.k.a. or s.f. parsethepart */ ( mcxTing* fmt , int offs , ofs* justify , ofs* width , int* repeat , mcxTing* scr , mcxTing* par /* size N_FORMAT_PARAMS */ ) { char* q /* find first % occurrence which is not %% */ ; char* p = fmt->str+offs ; mcxTing* msg = NULL ; mcxTing* part = NULL /* general fixme: convoluted success logic */ ; *justify = 4; /* fixme: insane justify logic (1,2,4,12, >> 3) */ ; mcxTingEmpty(scr, 0) ; while((q = strchr(p, '%'))) { if ((uchar) q[1] == '%') { mcxTingNAppend(scr, p, q+1-p) /* include one percent sign .. */ ; p = q+2 /* .. and skip the second one */ ; continue ; } else if ((uchar) q[1] == '{') { int cc = yamClosingCurly(fmt, q+1-fmt->str, NULL, RETURN_ON_FAIL) ; if (cc < 0) { msg = mcxTingPrint(NULL, "no closing scope") ; break ; } mcxTingNAppend(scr, p, q-p) ; part = mcxTingNNew(q+2, cc-1) ; offs = q+1+cc+1 - fmt->str ; } else msg = mcxTingPrint(NULL, "format sequence not recognized") ; break ; } if (!q) { mcxTingNAppend(scr, p, fmt->len - (p - fmt->str)) ; return 0 ; } if (part) { yamSeg* segpart = yamStackPushTmp(part) ; char* key ; while ((key = yamParseKV(segpart))) { if (!strcmp(key, "align") && n_args_g == 1) { if (strstr(arg1_g->str, "left")) *justify |= 1 ; else if (strstr(arg1_g->str, "right")) *justify |= 2 ; else if (strstr(arg1_g->str, "center")) *justify = 12 ; else yamErr("ignoring align mode <%s>", arg1_g->str) ; } else if (!strcmp(key, "padding") && n_args_g == 1) mcxTingNWrite(thepar(PADPATTERN), arg1_g->str, arg1_g->len) ; else if (!strcmp(key, "delimit")) { if (n_args_g == 2) { mcxTingNWrite(thepar(DELIMLEFT), arg1_g->str, arg1_g->len) ; mcxTingNWrite(thepar(DELIMRIGHT), arg2_g->str, arg2_g->len) ; } else if (n_args_g == 1) { mcxTingNWrite(thepar(DELIMLEFT), arg2_g->str, arg2_g->len) ; mcxTingNWrite(thepar(DELIMRIGHT), arg2_g->str, arg2_g->len) ; } ; } else if (!strcmp(key, "border") && n_args_g == 2) { mcxTingNWrite(thepar(BORDERLEFT), arg1_g->str, arg1_g->len) ; mcxTingNWrite(thepar(BORDERRIGHT), arg2_g->str, arg2_g->len) ; } else if (!strcmp(key, "alignat") && n_args_g == 2) { mcxTingNWrite(thepar(ATPIVOT), arg1_g->str, arg1_g->len) ; mcxTingNWrite(thepar(ATNUM), arg2_g->str, arg2_g->len) ; } else if (!strcmp(key, "double") && n_args_g == 1) { mcxTingNWrite(thepar(SUBS), arg1_g->str, arg1_g->len) /* subs takes a vararg * {arg}{foo}{left}{bar}{right}{zut} * et cetera. */ ; } else if (!strcmp(key, "length") && n_args_g >= 0) { int i ; mcxTingNWrite(thepar(LENKEY), arg1_g->str, arg1_g->len) ; for (i=2;i<=n_args_g;i++) /* mixed sign comparison */ mcxTingPrintAfter (thepar(LENARG), "{%s}", key_and_args_g[i].str) ; } else if (!strcmp(key, "width") && n_args_g == 1) *width = atoi(arg1_g->str) ; else if (!strcmp(key, "reuse") && n_args_g == 1) { if (!strcmp(arg1_g->str, "*")) *repeat = -1 ; else *repeat = atoi(arg1_g->str) ; } else yamErr ( "\\format#2" , "skipping unrecognized directive {%s} with %d arguments" , key , (int) n_args_g ) ; mcxFree(key) ; if (msg) break ; } yamStackFreeTmp(&segpart) ; mcxTingFree(&part) ; } if (msg) { yamErr("\\format#2", msg->str) ; offs = -1 ; } mcxTingFree(&msg) ; return offs ; } /* if lenkey && lenkey->len use it, otherwise use primitive length#1. * if (virarg && virarg->len) || !arg use virarg, otherwise use arg */ static dim get_length ( const mcxTing* arg , const mcxTing* virarg , const mcxTing* lenkey , const mcxTing* lenarg , yamSeg* seg ) { mcxTing* tmp = mcxTingPrint ( NULL , "\\%s{%s}%s" , (lenkey && lenkey->len ? lenkey->str : "length") , ((!arg || (virarg && virarg->len)) ? virarg->str : arg->str) , (lenkey && lenkey->len ? lenarg->str : "") ) ; dim l = 1 /* defensive (given seg->flags) non-0 non-BIG value */ ; if (yamDigest(tmp, tmp, seg)) NOTHING ; else l = atoi(tmp->str) ; mcxTingFree(&tmp) ; return l ; } static mcxTing* unprotect_arg ( const mcxTing* arg_in ) { mcxTing* arg = mcxTingNNew(arg_in->str, arg_in->len) ; yamUnprotect(arg) ; return arg ; } static void pad_left ( mcxTing* scr , const mcxTing* pattern_arg , dim width ) { mcxTing* pattern = unprotect_arg(pattern_arg) ; mcxTing* scr2 = NULL, *scr3 = NULL ; scr2 = mcxTingKAppend(NULL, pattern->str, (width + pattern->len) / pattern->len) ; mcxTingShrink(scr2, width) ; scr3 = yamProtect(scr2) ; mcxTingNAppend(scr, scr3->str, scr3->len) ; mcxTingFree(&pattern) ; mcxTingFree(&scr2) ; mcxTingFree(&scr3) ; } static void pad_right ( mcxTing* scr , const mcxTing* pattern_arg , dim width ) { mcxTing* pattern = unprotect_arg(pattern_arg) ; mcxTing* scr2 = NULL, *scr3 = NULL ; scr2 = mcxTingAppend(NULL, pattern->str + pattern->len - (width % pattern->len)) ; mcxTingKAppend(scr2, pattern->str, width / pattern->len) ; scr3 = yamProtect(scr2) ; mcxTingNAppend(scr, scr3->str, scr3->len) ; mcxTingFree(&pattern) ; mcxTingFree(&scr2) ; mcxTingFree(&scr3) ; } #define SUBS_HAVE_ARG 1 << 0 #define SUBS_HAVE_DELIMLEFT 1 << 1 #define SUBS_HAVE_DELIMRIGHT 1 << 2 mcxbits fill_subs ( mcxTing* spec , mcxTing* sub /* size N_FORMAT_SUBS */ ) { yamSeg* tmpseg = yamStackPushTmp(spec) ; mcxbits subs_on = 0 ; while (2 == yamParseScopes(tmpseg, 2, 0)) { if (!strcmp(arg1_g->str, "arg")) mcxTingNWrite(thesub(SUB_ARG), arg2_g->str, arg2_g->len) , subs_on |= SUBS_HAVE_ARG ; else if (!strcmp(arg1_g->str, "delimit-left")) mcxTingNWrite(thesub(SUB_DELIMLEFT), arg2_g->str, arg2_g->len) , subs_on |= SUBS_HAVE_DELIMLEFT ; else if (!strcmp(arg1_g->str, "delimit-right")) mcxTingNWrite(thesub(SUB_DELIMRIGHT), arg2_g->str, arg2_g->len) , subs_on |= SUBS_HAVE_DELIMRIGHT ; } yamStackFreeTmp(&tmpseg) ; return subs_on ; } yamSeg* yamFormat2 ( yamSeg* seg ) { mcxTing* fmt = mcxTingNew(arg1_g->str) ; mcxTing* args = mcxTingNew(arg2_g->str) ; mcxTing* out = mcxTingEmpty(NULL, 2*args->len) ; mcxTing* scr1 = mcxTingEmpty(NULL, 2*args->len) ; mcxTing* scr2 = mcxTingEmpty(NULL, args->len) ; mcxTing* arg = mcxTingEmpty(NULL, args->len) ; yamSeg* tmpseg = NULL ; int x = 0 ; int offs = 0 ; mcxbool ok = FALSE /* somewhat convoluted ok logic */ ; int repeat = 0 ; int justify_c = 0 /* cache */ ; int ll_field_c = 0 /* cache */ ; int ll_align_offset_c = 0 /* cache */ ; int subs_on_c = 0 /* cache */ ; mcxTing* par = mcxNAlloc(N_FORMAT_PARAMS, sizeof(mcxTing), mcxTingInit, RETURN_ON_FAIL) ; mcxTing* sub = mcxNAlloc(N_FORMAT_SUBS, sizeof(mcxTing), mcxTingInit, RETURN_ON_FAIL) ; do { if (!par || !sub) break ; if ( (yamDigest(args, args, seg)) || (yamDigest(fmt, fmt, seg)) ) /* NOTE: fmt digested */ break ; offs = 0 ; tmpseg = yamStackPushTmp(args) ; while (1) /* block longish, but it's not too bad */ { ofs justify = 0, ll_field = 0, ll_align_offset = 0 ; mcxbits subs_on = 0 ; ofs ll_arg /* logical length */ ; ofs ll_dlm_left ; ofs ll_dlm_right ; ofs lo_dlm_left = 0 /* logical offset */ ; ok = FALSE ; mcxTingEmpty(scr1, 0) ; mcxTingEmpty(scr2, 0) ; if (!repeat) { mcxTingEmpty(thepar(PADPATTERN), 0) ; mcxTingEmpty(thepar(DELIMLEFT), 0) ; mcxTingEmpty(thepar(DELIMRIGHT), 0) ; mcxTingEmpty(thepar(ATPIVOT), 0) ; mcxTingEmpty(thepar(ATNUM), 0) ; mcxTingEmpty(thepar(LENKEY), 0) ; mcxTingEmpty(thepar(LENARG), 0) ; mcxTingEmpty(thepar(SUBS), 0) ; mcxTingEmpty(thepar(BORDERLEFT), 0) ; mcxTingEmpty(thepar(BORDERRIGHT), 0) /* ^ perhaps mcxNApply is called for*/ ; mcxTingEmpty(thesub(SUB_ARG), 0) ; mcxTingEmpty(thesub(SUB_DELIMLEFT), 0) ; mcxTingEmpty(thesub(SUB_DELIMRIGHT), 0) /* scr1: write non-format part */ ; offs = ptp(fmt, offs, &justify, &ll_field, &repeat, scr1, par) ; if (!parlen(PADPATTERN)) mcxTingNWrite(thepar(PADPATTERN), " ", 1) ; if (!offs) /* trailing format part, no spec */ { ok = TRUE ; mcxTingNAppend(out, scr1->str, scr1->len) ; break ; } else if (offs < 0) /* error */ break ; if (parlen(SUBS)) subs_on = fill_subs(thepar(SUBS), sub) ; if (parlen(ATNUM)) ll_align_offset = atoi(parstr(ATNUM)) ; ll_field = includein(ll_field, 0, 4096) ; ll_align_offset = includein(ll_align_offset, 0, 4096) ; if (repeat) ll_field_c = ll_field , ll_align_offset_c = ll_align_offset , justify_c = justify , subs_on_c = subs_on ; } else { repeat-- ; ll_field = ll_field_c ; justify = justify_c ; ll_align_offset= ll_align_offset_c ; subs_on = subs_on_c ; } if ((x = yamParseScopes(tmpseg, 1, 0)) != 1) { if (repeat < 0) /* we are exhausting arguments */ ok = TRUE ; break ; } mcxTingNWrite(arg, arg1_g->str, arg1_g->len) ; ll_arg = get_length ( subs_on & SUBS_HAVE_ARG ? NULL : arg , thesub(SUB_ARG) , thepar(LENKEY) , thepar(LENARG) , seg ) ; ll_dlm_left = get_length ( subs_on & SUBS_HAVE_DELIMLEFT ? NULL : thepar(DELIMLEFT) , thesub(SUB_DELIMLEFT) , thepar(LENKEY) , thepar(LENARG) , seg ) ; ll_dlm_right = get_length ( subs_on & SUBS_HAVE_DELIMRIGHT ? NULL : thepar(DELIMRIGHT) , thesub(SUB_DELIMRIGHT) , thepar(LENKEY) , thepar(LENARG) , seg ) ; if (seg->flags & SEGMENT_INTERRUPT) break /* --> = --> = --> = --> = --> = --> = --> = --> = --> = --> = --> = --> = --> */ /* case 1: align at a string */ /* alignat{pivot}{num} */ ; if (ll_align_offset) { const mcxTing* thisarg = thesub(SUB_ARG)->len ? thesub(SUB_ARG) : arg ; char* alignat = strstr(thisarg->str, parstr(ATPIVOT)) /* futurefixme: strstr * It should work even with \{ etc, * as long as caller is consistent. */ ; int padsize = ll_field - ll_arg - (ll_dlm_left + ll_dlm_right) ; ofs ll_prefix = 0 ; if (!alignat) alignat = thisarg->str + thisarg->len /* say thisarg->str = 123::456 then prefix will be 123:: */ ; { mcxTing* prefix = mcxTingNWrite(NULL, thisarg->str, alignat-thisarg->str+parlen(ATPIVOT)) ; ll_prefix = get_length(prefix, NULL, thepar(LENKEY), thepar(LENARG), seg) ; mcxTingFree(&prefix) ; } if (seg->flags & SEGMENT_INTERRUPT) break ; if (padsize > 0) lo_dlm_left = ll_align_offset - ll_prefix - ll_dlm_left ; } /* case 2: left align */ else if (justify & 1) lo_dlm_left = 0 /* case 3: right align */ ; else if (justify & 2) lo_dlm_left = ll_field - ll_arg - ll_dlm_left - ll_dlm_right /* case 4: center */ ; else { int padsize = ll_field - ll_arg - (ll_dlm_left + ll_dlm_right) ; int delta = ((justify >> 3) + ll_field) % 2 ; lo_dlm_left = ((padsize+delta) / 2) ; } /* --> = --> = --> = --> = --> = --> = --> = --> = --> = --> = --> = --> = --> */ lo_dlm_left = includein(lo_dlm_left, 0, ll_field) ; { int ll /* logical length */ ; if (lo_dlm_left > 0) pad_left(scr2, thepar(PADPATTERN), lo_dlm_left) ; mcxTingNAppend(scr2, parstr(DELIMLEFT), parlen(DELIMLEFT)) ; mcxTingNAppend(scr2, arg->str, arg->len) ; mcxTingNAppend(scr2, parstr(DELIMRIGHT), parlen(DELIMRIGHT)) ; ll = lo_dlm_left + ll_dlm_left + ll_arg + ll_dlm_right ; if (ll < ll_field) pad_right(scr2, thepar(PADPATTERN), ll_field - ll) ; } mcxTingNAppend(out, scr1->str, scr1->len) ; mcxTingNAppend(out, parstr(BORDERLEFT), parlen(BORDERLEFT)) ; mcxTingNAppend(out, scr2->str, scr2->len) ; mcxTingNAppend(out, parstr(BORDERRIGHT), parlen(BORDERRIGHT)) ; ok = TRUE ; } } while (0) /* fixme or docme */ ; if (!ok && !(seg->flags & SEGMENT_INTERRUPT)) seg->flags |= SEGMENT_ERROR ; yamStackFreeTmp(&tmpseg) ; mcxTingFree(&scr1) ; mcxTingFree(&scr2) ; mcxTingFree(&arg) ; mcxNFree(par, N_FORMAT_PARAMS, sizeof(mcxTing), mcxTingRelease) ; mcxNFree(sub, N_FORMAT_SUBS, sizeof(mcxTing), mcxTingRelease) ; mcxTingFree(&args) ; mcxTingFree(&fmt) ; return yamSegPush(seg, out) ; } zoem-11-166/src/ops-env.c0000644000402500021140000001300211322627200012004 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include "ops-env.h" #include "util.h" #include "segment.h" #include "parse.h" #include "curly.h" #include "key.h" #include "sink.h" #include "digest.h" #include "util/ting.h" #include "util/hash.h" #include "util/alloc.h" #include "util/compile.h" typedef struct { mcxTing* init ; mcxTing* open ; mcxTing* close ; } envy ; static mcxHash* envTable_g = NULL; /* environment keys */ mcxstatus yamEnvNew ( const char* tag , const char* initstr , const char* openstr , const char* closestr , yamSeg* seg ) { mcxTing* opentag = mcxTingNew(tag) ; mcxbool ok = FALSE ; mcxKV* kv ; do { envy* e = NULL ; kv = mcxHashSearch(opentag, envTable_g, MCX_DATUM_INSERT) ; if (kv->key != opentag) { yamErr("\\env#4", "overwriting key <%s>",opentag->str) ; mcxTingFree(&opentag) ; } e = kv->val ; if (!e) { e = mcxAlloc(sizeof(envy), RETURN_ON_FAIL) ; if (!e) break ; e->init = mcxTingEmpty(NULL, 40) ; e->open = mcxTingEmpty(NULL, 80) ; e->close = mcxTingEmpty(NULL, 20) ; kv->val = e ; } mcxTingWrite(e->init, initstr) ; mcxTingWrite(e->open, openstr) ; mcxTingWrite(e->close, closestr) ; if (yamDigest(e->init, e->init, seg)) break ; ok = TRUE ; } while (0) ; if (!ok) { mcxTingFree(&opentag) ; return STATUS_FAIL ; } return STATUS_OK ; } const char* yamEnvOpen ( const char* label_ , const char* data_ , yamSeg* seg ) { mcxTing* label = mcxTingNew(label_) ; mcxTing* data = data_ ? mcxTingNew(data_) : NULL ; const char* val = NULL ; mcxKV* kv = mcxHashSearch(label, envTable_g, MCX_DATUM_FIND) ; mcxTing* lkey = mcxTingEmpty(NULL, 30) ; mcxTing* tg_tmp = mcxTingEmpty(NULL, 20) ; const char* me = "\\begin#2" ; mcxbool ok = FALSE ; while (1) { if (kv) { yamSeg* initseg = NULL ; envy* e = kv->val ; int x = 0 ; if (sinkDictPush(label->str)) /* localize everything */ break ; initseg = yamStackPushTmp(e->init) ; val = e->open->str ; while ((x = yamParseScopes(initseg, 2, 0)) == 2) { int delta = (uchar) arg1_g->str[0] == '$' ? 1 : 0 ; mcxTingPrint(tg_tmp, "$%s", arg1_g->str+delta) ; yamKeyDef(tg_tmp->str, arg2_g->str) ; } yamStackFreeTmp(&initseg) ; } else { yamErr(me, "env <%s> does not exist", label->str) ; break ; } if (data && data->len) { int x, n_args = 0 ; yamSeg* argseg ; yamKeyDef("$__args__", data->str) ; if (yamDigest(data, data, seg)) { yamErr (me, "arguments in env <%s> did not parse", label->str) ; break ; } yamKeyDef("$__xargs__", data->str) ; argseg = yamStackPushTmp(data) ; while ((x = yamParseScopes(argseg, 2, 0)) == 2) { int namelen = 0 ; mcxbits keybits = 0 ; int delta = (uchar) arg1_g->str[0] == '$' ? 1 : 0 ; mcxTingPrint(lkey, "$%s", arg1_g->str+delta) ; n_args++ ; if ( ( checkusrsig ( lkey->str, lkey->len, NULL, &namelen, &keybits ) != lkey->len /* mixed sign comparison */ ) || keybits & KEY_ZOEMONLY ) { yamErr(me, "invalid key <%s>", lkey->str) ; break ; } else yamKeySet(lkey->str, arg2_g->str) ; } yamStackFreeTmp(&argseg) ; mcxTingPrint(lkey, "%d", n_args) ; yamKeyDef("$0", lkey->str) ; } else yamKeyDef("$0", "0") , yamKeyDef("$__args__", "") , yamKeyDef("$__xargs__", "") ; ok = TRUE ; break ; } mcxTingFree(&label) ; mcxTingFree(&data) ; mcxTingFree(&lkey) ; mcxTingFree(&tg_tmp) ; return ok ? val : NULL ; } mcxstatus yamEnvClose ( const char* label_ ) { mcxTing* label = mcxTingNew(label_) ; mcxstatus status = STATUS_FAIL ; while (1) { if (sinkDictPop(label->str)) /* no trailing garbage */ break ; status = STATUS_OK ; break ; } mcxTingFree(&label) ; return status ; } const char* yamEnvEnd ( const char* label_ , yamSeg* seg_unused cpl__unused ) { mcxTing* label = mcxTingNew(label_) ; mcxKV* kv = mcxHashSearch(label, envTable_g, MCX_DATUM_FIND) ; mcxTingFree(&label) ; return kv ? ((envy*) kv->val)->close->str : NULL ; } void mod_env_init ( dim n ) { envTable_g = yamHashNew(n) ; } void envy_free ( void* envy_v ) { envy* e = envy_v ; mcxTingFree(&(e->init)) ; mcxTingFree(&(e->open)) ; mcxTingFree(&(e->close)) ; } void mod_env_exit ( void ) { mcxHashFree(&envTable_g, mcxTingRelease, envy_free) ; } zoem-11-166/src/ops-constant.c0000644000402500021140000000240410743355765013075 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include "ops-constant.h" #include "filter.h" #include "util.h" #include "curly.h" #include "util/hash.h" #include "util/ting.h" static mcxHash* cstTable_g = NULL; /* constants */ mcxTing* yamConstantGet ( mcxTing* key ) { mcxKV* kv = (mcxKV*) mcxHashSearch(key, cstTable_g, MCX_DATUM_FIND) ; return kv ? (mcxTing*) kv->val : NULL ; } /* fixme * is key really owned by yCN? */ mcxTing* yamConstantNew ( mcxTing* key , const char* val ) { mcxKV* kv = (mcxKV*) mcxHashSearch(key, cstTable_g, MCX_DATUM_INSERT) ; if ((mcxTing*) kv->key != key) mcxTingWrite((mcxTing*)kv->val, val) ; else kv->val = mcxTingNew(val) ; return (mcxTing*) kv->key ; } void mod_constant_init ( dim n ) { cstTable_g = yamHashNew(n) ; } void mod_constant_exit ( void ) { mcxHashFree(&cstTable_g, mcxTingRelease, mcxTingRelease) ; } zoem-11-166/src/curly.c0000644000402500021140000000742711065671111011575 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include "curly.h" #include "util.h" #include "source.h" #include "util/ting.h" #include "util/types.h" #include "util/compile.h" mcxTing* yamBlock ( const mcxTing* txt , int offset , int* lengthp , mcxTing* dst ) { int l = yamClosingCurly(txt, offset, NULL, RETURN_ON_FAIL) ; if (lengthp) *lengthp = l ; if (l <= 0) return NULL ; return mcxTingNWrite(dst, txt->str+offset+1, l-1) ; } /* * txt->str[offset] must be '{'. * returns l such that txt->str[offset+l] == '}'. */ int yamClosingCurly ( const mcxTing *txt , int offset , int* linect , mcxOnFail ON_FAIL ) { char* o = txt->str + offset ; char* p = o ; char* z = txt->str + txt->len ; int n = 1 /* 1 open bracket */ ; int lc = 0 ; int esc = 0 ; int q ; if (*p != '{') q = CURLY_NOLEFT ; else { while(++p < z) { if (*p == '\n') lc++ ; if (esc) { esc = 0 /* no checks for validity */ ; continue ; } switch(*p) { case '\\' : esc = 1; break ; case '{' : n++ ; break ; case '}' : n-- ; break ; } if (!n) break ; } q = n ? CURLY_NORIGHT : p-o ; } if (linect) *linect += lc ; if (q<0 && ON_FAIL == EXIT_ON_FAIL) yamScopeErr(NULL, "yamClosingCurly", q) ; return q ; } void yamScopeErr ( yamSeg *seg_unused cpl__unused , const char *caller , int error ) { if (error == CURLY_NORIGHT) yamErr ( caller , "unable to close scope (starting around line <%ld> in file <%s>)" , sourceGetLc() , sourceGetName() ) ; else if (error == CURLY_NOLEFT) yamErr ( caller , "scope error (around input line <%ld> in file <%s>)" , sourceGetLc() , sourceGetName() ) , yamErr(caller, "expected to see an opening '{'.") ; mcxExit(1) ; } /* * txt->str[offset] must be '{'. * returns l such that txt->str[offset+l] == '}'. */ int yamClosingCube ( const mcxTing *txt , int offset , int* linect , mcxOnFail ON_FAIL ) { char* o = txt->str + offset ; char* p = o ; char* z = txt->str + txt->len ; int lc = 0 ; int q ; if (*p != '<') q = CUBE_NOLEQ ; else { while(++p < z) { if (*p == '\n') lc++ ; else if (*p == '<' || *p == '>') break ; } q = *p == '<' ? CUBE_NEST : *p != '>' ? CUBE_NOGEQ : p-o ; } if (linect) *linect += lc ; if (q<0 && ON_FAIL == EXIT_ON_FAIL) yamScopeErr(NULL, "yamClosingGeq", q) ; return q ; } int yamEOConstant ( mcxTing *txt , int offset ) { char* o = txt->str + offset ; char* p = o ; char* z = txt->str + txt->len ; if (*p != '*') return(CONSTANT_NOLEFT) ; if (p[1] == '{') { int x = yamClosingCurly(txt,offset+1, NULL, RETURN_ON_FAIL) ; return x > 0 ? x+1 : CONSTANT_NORIGHT ; } while(++p < z) { if (*p == '\\' || *p == '{' || *p == '}') return (CONSTANT_ILLCHAR) ; if (*p == '*') break ; } return(*p == '*' ? p-o : CONSTANT_NORIGHT) ; } zoem-11-166/src/digest.c0000644000402500021140000001236010746342054011714 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under * the terms of the GNU General Public License; either version 3 of the * License or (at your option) any later version. You should have received a * copy of the GPL along with Zoem, in the file COPYING. */ #include #include "digest.h" #include "filter.h" #include "parse.h" #include "iface.h" #include "segment.h" #include "util.h" #include "util/ting.h" /* * creates successively new segs, and these segs * and their content will be freed. The input txt is left * alone however, and is responsibility of caller. */ mcxbits yamOutput ( mcxTing *txtin , sink* sk , int fltidx ) { yamSeg *seg ; filter* fd = sk ? sk->fd : NULL ; if (!txtin) yamErrx(1, "yamOutput PBD", "void argument") ; sinkPush(sk, fltidx) ; seg = yamStackPush(txtin) ; if (seg->flags & SEGMENT_ERROR) ; else while(seg) { int prev_offset = seg->offset ; yamSeg* prev_seg = seg ; mcxbool dofilter = fltidx ; int offset = yamFindKey(seg) ; mcxbool done = offset == -1 ; mcxbool err = offset == -2 ; int len ; if (err) break ; if (done) offset = seg->txt->len ; len = offset - prev_offset ; if (tracing_g & ZOEM_TRACE_OUTPUT) { fprintf ( stdout , "----.----. %s seg %d stack %d offset %d len %d txt len %d\n" , dofilter ? "filtering" : "skipping" , (int) seg->idx , (int) yamStackIdx() , (int) prev_offset , (int) len , (int) seg->txt->len ) ; if (dofilter && len) fputs(" ,,|", stdout) ; } if (len && dofilter && flts[fltidx](fd, seg->txt, prev_offset, len)) break ; if (seg && seg->flags & SEGMENT_INTERRUPT) break ; if (tracing_g & ZOEM_TRACE_OUTPUT) fprintf ( stdout , "%s----^----^ output %s seg %d and stack %d\n" , dofilter && len ? "\n" : "" , done ? "finished" : "continuing" , (int) seg->idx , (int) yamStackIdx() ) ; if (done) { seg = seg->prev ; yamSegFree(&prev_seg) ; } else { yamSeg* newseg = yamDoKey(seg) ; if (newseg) seg = newseg ; else { seg->flags |= SEGMENT_ERROR ; break ; } } } sinkPop(sk) ; if (seg) /* thrown or error */ { mcxbits flags = seg->flags & SEGMENT_INTERRUPT ; yamStackFree(&seg) ; return flags ; } return 0 ; } mcxbits yamDigest ( mcxTing *txtin , mcxTing *txtout , yamSeg *baseseg ) { yamSeg *seg ; mcxbool newscratch = txtin == txtout ? TRUE : FALSE ; mcxbits irupt = 0 ; mcxTing* txt = newscratch ? NULL : txtout ; if (!txtin) yamErrx(1, "yamDigest PBD", "void argument") ; if (txtin == txtout && !strchr(txtin->str, '\\')) return 0 ; txt = mcxTingEmpty(txt, 30) ; seg = yamStackPush(txtin) ; seg->flags |= SEGMENT_DIGEST ; if (seg->flags & SEGMENT_ERROR) ; else while(seg) { int prev_offset = seg->offset ; yamSeg* prev_seg = seg ; int offset = yamFindKey(seg) ; mcxbool done = offset == -1 ; mcxbool err = offset == -2 ; int len ; if (err) break ; if (done) offset = seg->txt->len ; len = offset - prev_offset ; if (tracing_g & ZOEM_TRACE_OUTPUT) fprintf ( stdout , "----.----. " "appending seg %d stack %d offset %d length %d text length %d%s" , (int) seg->idx , (int) yamStackIdx() , (int) prev_offset , (int) len , (int) seg->txt->len , len ? "\n(dat(" : "\n" ) ; if (len) mcxTingNAppend ( txt , seg->txt->str+prev_offset , len ) ; if (seg && seg->flags & SEGMENT_INTERRUPT) break ; if (tracing_g & ZOEM_TRACE_OUTPUT) { if (len) traceputlines(seg->txt->str+prev_offset, len) ; fprintf ( stdout , "----^----^ digest %s seg %d and stack %d\n" , done ? "finished" : "continuing" , (int) seg->idx , (int) yamStackIdx() ) ; } if (done) { seg = seg->prev ; yamSegFree(&prev_seg) ; } else { yamSeg* newseg = yamDoKey(seg) ; if (newseg) seg = newseg ; else { seg->flags |= SEGMENT_ERROR ; break ; } } } if (newscratch) { mcxTingWrite(txtin, txt->str) ; mcxTingFree(&txt) ; } if (seg) /* thrown or error */ { irupt = seg->flags & SEGMENT_INTERRUPT ; if (baseseg) baseseg->flags |= irupt ; yamStackFree(&seg) ; } return irupt ; } zoem-11-166/src/entry.c0000644000402500021140000001551011304751313011567 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include #include #include #include #include "ops.h" #include "ops-xtag.h" #include "ops-constant.h" #include "ops-grape.h" #include "ops-env.h" #include "key.h" #include "source.h" #include "read.h" #include "iface.h" #include "filter.h" #include "key.h" #include "digest.h" #include "parse.h" #include "util.h" #include "version.h" #include "../config.h" #include "util/ting.h" #include "util/io.h" #include "util/types.h" #include "util/ding.h" #include "util/err.h" #include "util/tr.h" #define STRING_h(x) #x #define STRING(x) STRING_h(x) dim buckets_user = 1200; /* 600 */ dim buckets_zoem = 1200; /* 200 */ mcxTing* make_searchpath ( const char* zip ) { mcxTing* sp = mcxTingNew(zip) ; mcxTing* zsp = NULL ; char *q = NULL, *p = sp->str ; mcxTingTr(sp, ":[:space:]", " [* *]", NULL, "[:space:]", 0) ; while (p && pstr+sp->len) { while (isspace((unsigned char) *p)) p++ ; q = mcxStrChrIs(p, isspace, -1) ; if (q) *q = '\0' ; zsp = mcxTingPrintAfter(zsp, "{%s}", p) ; if (q) *q = ' ' ; p = q ; } mcxTingFree(&sp) ; return zsp ; } /* * The file IO init stuff is still slightly kludgy and ad hoc * (it used to be worse) - it is somewhat split over zoem.c and entry.c * The reason is that it's a bit of if-else spaghetti for deciding * what to do in the presence of various combinations of (mainly) * -i, -o, -e, and -E, and whether stdin/stdout arguments are present. * Remember that when none of -i, -I, -o is specified, we do * interactive mode. * The rest of zoem is a lot cleaner, even if zoem is a dirty language :) */ mcxstatus yamEntry ( const char* sfnentry , const char* sfnpath , const char* sfnbase , size_t chunk_size , const char* sfnout , const char* sdevice , int fltidx , mcxbits trace_flags , mcxbits entry_flags , mcxTing* vars , mcxTing* expr ) { mcxTing* fnentry = mcxTingNew(sfnentry) ; mcxTing* fnout = mcxTingNew(sfnout) ; mcxTing* fnpath = mcxTingNew(sfnpath) ; mcxTing* fnbase = mcxTingNew(sfnbase) ; const char* zip = STRING(INCLUDEPATH) ; mcxbool debug = entry_flags & ENTRY_DEBUG ; mcxbool stdia = entry_flags & ENTRY_STDIA ; mcxTing* zsp ; mcxIO *xfout = NULL ; mcxTing *filetxt = NULL /* involved in interactive hackery */ ; const char* me = "zoem main" ; mcxbits flag_zoem = 0 ; mcxstatus status = STATUS_OK ; if (!stdia) { if (entry_flags & ENTRY_STDIN) fprintf(stderr, "=== reading from stdin\n") ; if (entry_flags & ENTRY_STDOUT) fprintf(stderr, "=== writing to stdout\n") ; filetxt = mcxTingEmpty(NULL, 1000) ; } /* check enter_interactive should print something I guess */ mod_key_init ( buckets_user ) ; mod_read_init ( 5 ) ; mod_env_init ( 20 ) ; mod_grape_init ( ) ; mod_ops_init ( buckets_zoem ) ; mod_xtag_init ( ) ; mod_source_init ( ) ; mod_sink_init ( 10 ) ; mod_constant_init ( 50 ) ; mod_filter_init ( 10 ) ; mod_segment_init ( ) ; mod_parse_init (trace_flags) ; mod_ops_digest ( ) /* create \begin{} env */ ; yamKeyDef("__device__", *sdevice ? sdevice : "__none__") ; yamKeyDef("__fnbase__", fnbase->str) ; yamKeyDef("__fnpath__", fnpath->str) ; yamKeyDef("__fnentry__", fnentry->str) ; yamKeyDef("__version__", zoemDateTag) ; yamKeyDef("__sysval__", "0") ; yamKeyDef("__lc__", "{") ; yamKeyDef("__split__", (entry_flags & ENTRY_SPLIT) ? "1" : "0") ; yamKeyDef("__rc__", "}") ; yamKeyDef("__parmode__", "16") ; zsp = make_searchpath(zip) ; yamKeyDef("__searchpath__", zsp->str) /* fixme, enable setx */ ; if (vars && vars->len) /* fixme, hide details */ { char *p = vars->str ; char *r, *q ; mcxbits keybits = 0 ; int namelen = 0 ; while ((q = strchr(p, '\036'))) { *q = '\0' ; if ((r = strchr(p, '='))) *r = '\0' ; if ( strlen(p) != checkusrsig(p, strlen(p), NULL, &namelen, &keybits) ) /* mixed sign comparison */ yamErrx(1, "init", "key <%s> not acceptable", p) ; yamKeySet(p, r ? r+1 : "1") ; p = q+1 ; } } /* this works for -e and -E (expression) options, * because those arguments are embedded in \write#3, * which issues yamOutputNew also - so \__fnout__ is always set. */ if (!(xfout = yamOutputNew(fnout->str))) yamErrx(1, "init", "no output stream") ; sinkPush(xfout->usr, fltidx) /* this sets up our default sink */ ; if (expr->len) { flag_zoem = yamOutput(expr, xfout->usr, ZOEM_FILTER_DEVICE) ; if (flag_zoem & (SEGMENT_THROW | SEGMENT_ERROR)) { mcxErr(me, "Expression: unwound on error") ; if (debug) enter_interactive() ; } } if (entry_flags & ENTRY_EXXIT) /* * if e.g. zoem -i - -E foo, * foo gets printed only after is pressed. * the reason is we are hanging out here below. */ ; else if (!flag_zoem && !stdia) { mcxTing *fn = mcxTingNew(fnentry->str) ; mcxbits mode = SOURCE_DEFAULT_SINK | SOURCE_NO_SEARCH ; if (debug) mode |= SOURCE_DEBUG ; status = sourceAscend (fn, mode, chunk_size) /* the big one */ ; if (status == STATUS_FAIL_OPEN) yamErr("zoem", "cannot open file <%s>", fnentry->str) ; mcxTingFree(&fn) ; } else if (stdia) enter_interactive() ; if (trace_flags & ZOEM_TRACE_HASH) yamStats() ; mod_registrees() ; sinkPop(xfout->usr) ; mod_env_exit() ; mod_ops_exit() ; mod_xtag_exit() ; mod_key_exit() ; mod_filter_exit() ; mod_read_exit() ; mod_source_exit() ; mod_sink_exit() ; mod_constant_exit() ; mod_parse_exit() ; mod_grape_exit() ; mod_iface_exit() ; mod_segment_exit() ; mcxTingFree(&filetxt) ; mcxTingFree(&fnbase) ; mcxTingFree(&fnpath) ; mcxTingFree(&fnentry) ; mcxTingFree(&fnout) ; mcxTingFree(&zsp) ; return status ; } zoem-11-166/src/iface.c0000644000402500021140000000610311444414252011476 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include #include int ENTRY_SPLIT = 1; int ENTRY_EXXIT = 2; int ENTRY_DEBUG = 4; int ENTRY_STDIA = 8; int ENTRY_STDIN = 16; int ENTRY_STDOUT = 32; int SYSTEM_SAFE = 13 ; int SYSTEM_UNSAFE = 17 ; int SYSTEM_UNSAFE_SILENT = 19 ; mcxTing* system_allow = NULL; int systemAccess = 13 ; /* for ops.c, system#3 */ int systemHonor = 0 ; /* for ops.c, system#3 */ int stressWrite = 0 ; /* for ops.c, write#3 */ size_t chunk_size = 1 << 20 ; /* for entry.c and ops.c, dofile#1 */ int ztablength_g = 0 ; /* for filter.c, \I step size */ int readlineOK = 1 ; char *tracestrings[] = { "trace in long mode, do not truncate lines" #define TRACE_LONG 1 , "print keys" #define TRACE_KEYS 2 , "print arguments" #define TRACE_ARGS 4 , "print key definitions" #define TRACE_DEFS 8 , "print scopes (varargs)" #define TRACE_SCOPES 16 , "print segment information" #define TRACE_SEGS 32 , "trace filtering and output" #define TRACE_OUTPUT 64 , "trace regexes (\\inspect#4)" #define TRACE_REGEX 128 , "trace IO" #define TRACE_IO 256 , "trace spawned system calls" #define TRACE_SYSTEM 512 , "trace let (arithmetic module)" #define TRACE_LET 1024 , "print hash table stats at exit" #define TRACE_HASH 2048 , "trace primitives in user syntax" #define TRACE_PRIME 4096 } ; int n_tracebits = sizeof(tracestrings) / sizeof(char*); #define TRACE_PREVIOUS -1 #define TRACE_DEFAULT TRACE_KEYS | TRACE_ARGS #define TRACE_ALL ((1 << 11) - 2) #define TRACE_ALL_LONG ((1 << 11) - 1) int ZOEM_TRACE_LONG = TRACE_LONG ; int ZOEM_TRACE_KEYS = TRACE_KEYS ; int ZOEM_TRACE_ARGS = TRACE_ARGS ; int ZOEM_TRACE_DEFS = TRACE_DEFS ; int ZOEM_TRACE_SCOPES = TRACE_SCOPES ; int ZOEM_TRACE_SEGS = TRACE_SEGS ; int ZOEM_TRACE_OUTPUT = TRACE_OUTPUT ; int ZOEM_TRACE_REGEX = TRACE_REGEX ; int ZOEM_TRACE_HASH = TRACE_HASH ; int ZOEM_TRACE_IO = TRACE_IO ; int ZOEM_TRACE_SYSTEM = TRACE_SYSTEM ; int ZOEM_TRACE_LET = TRACE_LET ; int ZOEM_TRACE_PRIME = TRACE_PRIME ; int ZOEM_TRACE_PREVIOUS = TRACE_PREVIOUS; int ZOEM_TRACE_DEFAULT = TRACE_DEFAULT ; int ZOEM_TRACE_ALL = TRACE_ALL ; int ZOEM_TRACE_ALL_LONG = TRACE_ALL_LONG; void showTracebits ( void ) { int i ; for (i=0;i #include #include #include #include #include #include #include "../config.h" #include "filter.h" #include "util.h" #include "entry.h" #include "key.h" #include "source.h" #include "read.h" #include "digest.h" #include "iface.h" #include "util/hash.h" #include "util/ting.h" #include "util/types.h" #include "util/io.h" #include "util/minmax.h" #ifdef HAVE_READLINE_READLINE_H #include #include #define HAVE_READLINE 1 #endif const char* ia_sep = "<-------------- zoem -------------->"; typedef struct { long plc /* perceived line count */ ; int delta /* at perceived line count lc, add delta */ ; } linecc ; /* line count compensator */ typedef struct { mcxTing* fname ; const mcxTing* txt ; long linect /* *current* line count while parsing */ ; mcxGrim* src_lcc ; mcxLink* lst_lcc ; } inputHook ; inputHook inputHookDir[] = { { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } , { NULL, NULL, 1, NULL, NULL } } ; #define MAX_FILES_NEST ((int) (sizeof inputHookDir / sizeof(inputHook))) #define hd inputHookDir static int hdidx_g = -1; /* Careful! should never be less than -1 */ void mod_source_init ( void ) { yamKeySet("__fnin__", "_nil_") ; yamKeySet("__fnup__", "the_invisible_hand") ; } void mod_source_exit ( void ) { dim i ; for (i=0;i= 0) mcxGrimFree(&(hd[hdidx_g].src_lcc)) , mcxListFree(&(hd[hdidx_g].lst_lcc), NULL) ; hdidx_g-- ; if (hdidx_g >= 0) yamKeySet("__fnin__", hd[hdidx_g].fname->str) ; if (hdidx_g >= 1) yamKeySet("__fnup__", hd[hdidx_g-1].fname->str) ; return STATUS_OK ; } mcxstatus sourcePush ( const char* str , const mcxTing* txt ) { linecc* lcc ; hdidx_g++ /* now at least >= 0 */ ; if (hdidx_g >= MAX_FILES_NEST && hdidx_g--) return STATUS_FAIL ; hd[hdidx_g].linect = 1 ; hd[hdidx_g].txt = txt ; hd[hdidx_g].src_lcc = mcxGrimNew(sizeof(linecc), 10, MCX_GRIM_GEOMETRIC) ; lcc = mcxGrimGet(hd[hdidx_g].src_lcc) ; lcc->plc = 1 ; lcc->delta = 0 ; hd[hdidx_g].lst_lcc = mcxListSource(10, MCX_GRIM_GEOMETRIC) /* * Fixme/document: listSource is given a value; */ ; hd[hdidx_g].lst_lcc->val = lcc /* * Why use mcxGrimGet above? */ ; if (hd[hdidx_g].fname) mcxTingWrite(hd[hdidx_g].fname, str) ; else hd[hdidx_g].fname = mcxTingNew(str) ; yamKeySet("__fnin__", str) ; if (hdidx_g >= 1) yamKeySet("__fnup__", hd[hdidx_g-1].fname->str) ; return STATUS_OK ; } mcxbool sourceCanPush ( void ) { return (hdidx_g+1) < MAX_FILES_NEST ? TRUE : FALSE ; } long sourceGetLc ( void ) { inputHook* hk = hdidx_g >= 0 ? hd+hdidx_g : hd+0 ; mcxLink* lk = hk->lst_lcc ; linecc* lcc = lk->val ; while (lk->prev && lcc->plc > hk->linect) { lk = lk->prev ; lcc = lk->val ; } return hk->linect + lcc->delta ; } const char* sourceGetName ( void ) { return hdidx_g >= 0 ? hd[hdidx_g].fname->str : "" ; } mcxTing* sourceGetPath ( void ) { char* s ; char* a = hdidx_g < 0 ? NULL : hd[hdidx_g].fname->str ; if (!a) return NULL ; if (!(s = strrchr(a, '/'))) return NULL ; return mcxTingNNew(a, s-a+1) ; } void sourceIncrLc ( const mcxTing* txt , int d ) { if (!txt || hd[hdidx_g].txt == txt) hd[hdidx_g].linect += d /* case !txt is used for inline file ___jump_lc___ hack */ ; } void enter_interactive ( void ) { mcxTing* txt = mcxTingNew("\\zinsert{stdia}") ; yamDigest(txt, txt, NULL) ; mcxTingFree(&txt) ; } static void lcc_update ( long n_deleted , long n_lines , void* data ) { inputHook* hk = data ; linecc* lcc = mcxGrimGet(hk->src_lcc) ; lcc->delta = (((linecc*) hk->lst_lcc->val)->delta) + n_deleted ; lcc->plc = n_lines - lcc->delta ; hk->lst_lcc = mcxLinkAfter(hk->lst_lcc, lcc) ; } mcxstatus sourceAscend ( mcxTing *fnsearch , mcxbits modes , size_t chunk_size ) { int fltidx = modes & SOURCE_DEFAULT_SINK ? ZOEM_FILTER_DEFAULT : ZOEM_FILTER_NONE ; size_t sz_file = 0 ; size_t sz_chunk = 0 ; mcxTing* filetxt = mcxTingEmpty(NULL, 1000) ; mcxbool use_searchpath = !(modes & SOURCE_NO_SEARCH) ; mcxbool allow_inline = !(modes & SOURCE_NO_INLINE) ; mcxbool debug = (modes & SOURCE_DEBUG) ; const mcxTing* inline_txt = NULL ; const mcxTing** inline_txt_ptr = allow_inline ? &inline_txt : NULL ; mcxIO *xf = yamTryOpen(fnsearch, inline_txt_ptr, use_searchpath) ; mcxstatus stat_open = STATUS_OK ; mcxstatus stat_read = STATUS_OK ; mcxbits flag_zoem = 0 ; if (inline_txt) mcxTingWrite(filetxt, inline_txt->str) , stat_read = STATUS_DONE ; else if (xf) { struct stat mystat ; if (!xf->stdio) { if (stat(xf->fn->str, &mystat)) mcxErr("sourceAscend", "can not stat file <%s>", xf->fn->str) ; else { if (!chunk_size) sz_chunk = mystat.st_size ; else if (chunk_size) sz_chunk = MCX_MIN(mystat.st_size, 1.1 * chunk_size) ; sz_file = mystat.st_size ; } if (sz_chunk) mcxTingEmpty(filetxt, sz_chunk) ; } } else stat_open = STATUS_FAIL ; if (stat_open == STATUS_OK) { long n_lines_read = 0 ; long n_chunk = 0 ; sourcePush(xf->fn->str, filetxt) ; while(1) { if (!inline_txt) { stat_read = yamReadChunk ( xf , filetxt , 0 , chunk_size , &n_lines_read , lcc_update , hd+hdidx_g ) ; if (stat_read != STATUS_OK && stat_read != STATUS_DONE) break ; } if ((flag_zoem = yamOutput(filetxt, NULL, fltidx))) { if (flag_zoem & SEGMENT_DONE) flag_zoem = 0 ; else { mcxErr("zoem", "unwound on error/exception") ; if (debug) /* fixme; could also enter debug in caller? */ enter_interactive() ; } break ; } if (inline_txt) break ; if ( xf && ( stat_read == STATUS_OK || (n_chunk && stat_read == STATUS_DONE) ) ) mcxTell("zoem", "read chunk of size <%ld>", (long) filetxt->len) ; if (stat_read == STATUS_DONE) break ; if (hdidx_g == 3) fprintf(stdout, "[%s]\n", filetxt->str) ; n_chunk++ ; } sourcePop() ; } mcxTingFree(&filetxt) ; mcxIOfree(&xf) ; if (stat_open) return STATUS_FAIL_OPEN ; if (stat_read != STATUS_DONE) return STATUS_FAIL_READ ; if (flag_zoem) return STATUS_FAIL_ZOEM ; return STATUS_OK ; } void ia_separate ( mcxTing* tmp ) { mcxTing* ump = yamKeyGet(tmp) ; fprintf(stdout, "%s\n", ump ? ump->str : ia_sep) ; fflush(stdout) ; } void sourceStdia ( mcxTing* filetxt ) { mcxIO* xfin = mcxIOnew("-", "r") ; mcxTing* tmp = mcxTingNew("__parmode__") ; mcxTing* ump = yamKeyGet(tmp) ; int parmode = ump ? atoi(ump->str) : MCX_READLINE_DOT ; mcxbool use_readline = FALSE ; const char* me = "stdia" ; mcxbits flag_zoem = 0 ; sink *my_sink ; mcxIO* xfout = NULL #if HAVE_READLINE ; use_readline = readlineOK #endif ; mcxTingWrite(tmp, "__ia__") ; if ( mcxIOopen(xfin, RETURN_ON_FAIL) || !(xfout = yamOutputNew("-")) ) yamErrx(1, "init PBD", "failure opening interactive session") ; my_sink = xfout->usr ; /* sinkPush(xfout->usr, ZOEM_FILTER_DEVICE) * No longer necessary with the new framework. * Temporarily left as a reminder of old-times */ #define VERBOSE_IA 1 ; if (VERBOSE_IA) { fprintf ( stdout , "%s%s%s" , "=== Interactive session, I should recover from errors.\n" "=== If I exit unexpectedly, consider sending a bug report.\n" , parmode & MCX_READLINE_DOT ? "=== A single dot on a line of its own triggers interpretation.\n" : "" , "=== Separator can be changed through key __ia__ .\n" ) ; if (use_readline) fprintf(stdout, "=== Readline enabled.\n") ; fflush(stdout) ; } #if HAVE_READLINE if (use_readline) { while (1) { char* line = readline("") ; if (!line) break ; if (strcmp(".", line)) { mcxTingPrintAfter(filetxt, "%s\n", line) ; add_history(line) ; continue ; } ; if (VERBOSE_IA) ia_separate(tmp) ; sourcePush(me, filetxt) ; if ((flag_zoem = yamOutput(filetxt, my_sink, ZOEM_FILTER_DEFAULT))) { const char* type = flag_zoem & SEGMENT_THROW ? "exception" : flag_zoem & SEGMENT_DONE ? "EOP" : "error" ; fprintf(stdout, "(interactive %s)\n", type) ; } fflush(stdout) ; sourcePop() ; filterLinefeed(my_sink->fd, stdout) ; if (xfin->ateof) break ; if (VERBOSE_IA) ia_separate(tmp) ; mcxTingEmpty(filetxt, 0) ; } } else #endif while (STATUS_OK == mcxIOreadLine(xfin, filetxt, parmode)) { if (VERBOSE_IA) ia_separate(tmp) ; sourcePush(me, filetxt) ; if ((flag_zoem = yamOutput(filetxt, my_sink, ZOEM_FILTER_DEFAULT))) { const char* type = flag_zoem & SEGMENT_THROW ? "exception" : flag_zoem & SEGMENT_DONE ? "EOP" : "error" ; fprintf(stdout, "(interactive %s)\n", type) ; } fflush(stdout) ; sourcePop() ; filterLinefeed(my_sink->fd, stdout) ; if (xfin->ateof) break ; if (VERBOSE_IA) ia_separate(tmp) ; } /* sinkPop(xfout->usr) */ ; mcxTingFree(&tmp) ; mcxIOfree(&xfin) ; } zoem-11-166/src/sink.c0000644000402500021140000002107011330316127011367 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ /* TODO. * Most of the logic is concentrated in sinkPush. It is a bit dense * and underdocumented. */ #include #include "filter.h" #include "util.h" #include "entry.h" #include "key.h" #include "read.h" #include "sink.h" #include "util/hash.h" #include "util/ting.h" #include "util/types.h" #include "util/alloc.h" #include "util/io.h" #include "util/minmax.h" #include "util/compile.h" #ifdef DEBUG # define DEBUG_BU DEBUG #endif #define DEBUG 0 typedef struct { mcxLink* sp ; } busystack ; static busystack bst = { NULL } ; static busystack* busystack_g = &bst ; sink* sink_default_g = NULL ; static int sink_fltidx_g = 0 ; /* ZOEM_FILTER_NONE */ static mcxHash* wrtTable_g = NULL ; /* open output files */ static dim n_dict_dollar_max = 100 ; void mod_sink_init ( dim n ) { wrtTable_g = yamHashNew(n) ; busystack_g->sp = mcxListSource(10, MCX_GRIM_ARITHMETIC) ; } /* { mcxIO* xf = yamOutputNew("foobar") ; sinkPush(xf->usr, ZOEM_FILTER_NONE) ; */ void warn_stack_free ( lblStack** st , const char* type , const char* file ) { mcxLink* lk = (*st)->sp ; while (lk->prev) { mcxErr ( "env" , "file <%s> open %s <%s>" , file , type , ((mcxTing*)lk->val)->str ) ; lk = lk->prev ; } ting_stack_free(st) ; } void sinkFree ( sink* sk ) { filterFree(sk->fd) ; warn_stack_free(&(sk->xmlStack), "tag", sk->fname) ; dictStackFree(&(sk->dlrStack), "env", sk->fname) ; mcxFree(sk->fname) ; mcxFree(sk) ; } void yamOutputClose ( const char* s ) { mcxTing* fname = mcxTingNew(s) ; mcxKV* kv = mcxHashSearch(fname, wrtTable_g, MCX_DATUM_FIND) ; if (kv) { mcxIO* xf = (mcxIO*) kv->val ; fflush(xf->fp) ; mcxIOclose(xf) ; } /* keep the object around; repeated \writeto should append * (this might be settable someday) */ mcxTingFree(&fname) ; } sink* sinkNew ( mcxIO* xf ) { sink* sk = mcxAlloc(sizeof(sink), EXIT_ON_FAIL) ; sk->fd = xf ? filterNew(xf->fp) : NULL ; sk->xmlStack = ting_stack_new(10) ; sk->dlrStack = dictStackNew(20, n_dict_dollar_max, "''") ; sk->fname = mcxTingStr(xf->fn) ; return sk ; } mcxIO* yamOutputNew ( const char* s ) { mcxIO *xf = NULL ; mcxTing *fname = mcxTingNew(s) ; mcxKV *kv ; if (fname->len > 1024) { yamErr ( "yamOutputNew" , "output file name expansion too <%d> long" , fname->len ) ; mcxTingFree(&fname) ; return NULL ; } kv = mcxHashSearch(fname, wrtTable_g, MCX_DATUM_FIND) ; if (!kv) { xf = mcxIOnew(fname->str, "w") ; kv = mcxHashSearch(fname, wrtTable_g, MCX_DATUM_INSERT) ; kv->val = xf ; } else { xf = (mcxIO*) kv->val ; if (!xf->fp) /* used by writeto wrapper */ mcxIOrenew(xf, NULL, "a") ; mcxTingFree(&fname) ; } if (!xf->fp && mcxIOopen(xf, RETURN_ON_FAIL) != STATUS_OK) { yamErr ( "yamOutputNew" , "can not open file <%s> for writing\n" , s ) ; if (!(kv = mcxHashSearch(xf->fn, wrtTable_g, MCX_DATUM_DELETE))) { yamErr ( "yamOutputNew panic" , "can not find IO object for stream <%s>" , xf->fn->str ) ; return NULL ; } fname = ((mcxTing*) (kv->key)) ; mcxTingFree(&fname) /* might have xf->usr (in renewal case) should free it as well * (check though) */ ; mcxIOfree(&xf) ; return NULL ; } if (!xf->usr) xf->usr = sinkNew(xf) ; else filterSetFP(((sink*) xf->usr)->fd, xf->fp) /* this case is relevant for "a"(ppend) renewal (only), * as the fp will have changed */ ; return xf ; } void yamIOfree_v ( void* xf_v ) { mcxIO* xf = xf_v ; sinkFree((sink*) xf->usr) ; xf->usr = NULL ; mcxIOrelease(xf) ; mcxTingFree(&xf->buffer) /* fixme: crosses boundary */ ; } void mod_sink_exit ( void ) { mcxHashFree(&wrtTable_g, mcxTingRelease, yamIOfree_v) ; mcxListFree(&(busystack_g->sp), NULL) ; } #if 1 void sink_stack_debug ( void ) { mcxLink* lk = busystack_g->sp ; while (lk) { busysink* bs = lk->val ; if (bs && bs->sk) fprintf ( stderr , "name [%s] fd [%p]\n" , bs->sk->fname, (void*) bs->sk->fd ) ; lk = lk->prev ; } } #endif void sinkSetFNOUT ( void ) { yamKeySet("__fnout__", sink_default_g->fname) ; } busysink* new_busy_sink ( void ) { return mcxAlloc(sizeof(busysink), EXIT_ON_FAIL) ; } /* NOTE. * In the stack of sinks the same sink may occur multiple times. * when we issue writeto (redirect current default output stream) * it has to be updated in all places. * This design may be a case of legacy overengineering. Need * an example where the stack is actually *used* */ void sinkPush ( sink* new_active_sink , int fltidx ) { mcxLink* busylk= busystack_g->sp ; busysink* curr = busylk->val ; busysink* next = NULL ; mcxbool write_to = fltidx < 0 ; mcxbool change_default = write_to || !sink_default_g ;if(0)fprintf(stderr, "boot=%d writeto=%d new=%d\n", sink_default_g ? 0 : 1, write_to ? 1 : 0, new_active_sink ? 1 : 0) #if DEBUG ; fprintf(stderr, "=== %p %d\n", (void*) new_active_sink, fltidx) #endif ; if (change_default) { if (sink_default_g && new_active_sink) while (busylk && curr) /* find all occurrences of target */ { if (curr->sk == sink_default_g) curr->sk = new_active_sink /* old sk is cached in wrtTable_g */ ; busylk = busylk->prev ; curr = busylk->val ; } #if DEBUG fprintf (stderr, "--> change sink to %s\n", new_active_sink->fname) #endif ; if (!sink_default_g) sink_fltidx_g = fltidx ; if (new_active_sink) sink_default_g = new_active_sink ; sinkSetFNOUT() ; } if (write_to) return /* otherwise push on stack */ ; next = new_busy_sink() /* uninitialized */ ; if (!new_active_sink) /* dofile or chunk (<- yamOutput) */ next->sk = sink_default_g ; else next->sk = new_active_sink /* next is now active sink */ ; busystack_g->sp = mcxLinkAfter(busystack_g->sp, next) ; } void sinkPop ( sink* sk cpl__unused ) { mcxLink* lk = busystack_g->sp->prev ; busysink* curr = busystack_g->sp->val #if DEBUG ; fprintf ( stderr , "--> pop %s curr %s\n" , curr->sk->fname , sk ? sk->fname : "none" ) #endif ; mcxFree(curr) ; mcxLinkDelete(busystack_g->sp) ; busystack_g->sp = lk ; } keyDict* sinkGetDLRtop ( void ) { sink* sk = ((busysink*) busystack_g->sp->val)->sk ; mcxLink* sp = busystack_g->sp ;if(0)sink_stack_debug() ;if(0)fprintf(stderr, "DLRtop return %s\n", sk->fname) ; return sk->dlrStack->top ; } /* return ((busysink*) busystack_g->sp->val)->sk->dlrStack->top */ keyDict* sinkGetDLRdefault ( void ) { ;if(0)fprintf(stderr, "DLRdefault return %s\n", sink_default_g->fname) ; return sink_default_g->dlrStack->top ; } dictStack* sinkGetDLR ( void ) { return ((busysink*) busystack_g->sp->val)->sk->dlrStack ; } sink* sinkGet ( void ) { return ((busysink*) busystack_g->sp->val)->sk ; } lblStack* sinkGetXML ( void ) { return ((busysink*) busystack_g->sp->val)->sk->xmlStack ; } const char* sinkGetDefaultName ( void ) { return sink_default_g->fname ; } mcxstatus sinkDictPush ( const char* label ) { dictStack* dlr = sinkGetDLR() ; return dictStackPush(dlr, 16, label) ; } mcxstatus sinkDictPop ( const char* name ) { dictStack* dlr = sinkGetDLR() ; return dictStackPop(dlr, "dollar", name) ; } void sinkULimit ( dim size ) { n_dict_dollar_max = size ; } #ifdef DEBUG_BU # define DEBUG DEBUG_BU # undef DEBUG_BU #endif zoem-11-166/src/filter.c0000644000402500021140000005177111255402577011736 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include #include #include "filter.h" #include "curly.h" #include "util.h" #include "ops-constant.h" #include "digest.h" #include "sink.h" #include "key.h" #include "iface.h" #include "parse.h" #include "util/alloc.h" #include "util/minmax.h" #include "util/list.h" #include "util/ding.h" /* filterAt is called by: * filterDevice * yamputc in plain mode. * yamPutConstant * yamSpecialPut * * yamputc in plain mode is called by: * filterDevice * * yamputc in at mode is called by: * filterAt * * yamPutConstant is called by * filterDevice * * yamSpecialPut is called by * filterDevice * * filterTxt calls none of the above * filterCopy calls none of the above */ /* n_newlines is the number of newlines that form the trailing * part of the relevant output sink. * If the last character was not a newline, this count is zero. * If the last N characters were newlines, this count is N. */ struct filter { int indent ; int n_newlines /* currently flushed newline count */ ; int n_spaces /* currently *stacked* space count */ ; int doformat ; int level ; FILE* fp ; } ; mcxstatus filterDevice ( filter* fd , mcxTing* txt , int offset , int bound ) ; void yamputc ( filter* fd , unsigned char c , int atcall ) ; #define N_SPECIAL 259 #define SPECIAL_SPACE 256 #define SPECIAL_BREAK 257 #define SPECIAL_DASH 258 typedef struct yamSpecial { mcxTing* txt ; struct yamSpecial*up ; } yamSpecial ; static yamSpecial specials[N_SPECIAL]; static mcxTing* zconstant = NULL; static mcxTing* ampersand = NULL; static mcxTing* semicolon = NULL; int yamAtDirective ( filter* fd , char c ) ; mcxstatus filterAt ( filter* fd , mcxTing* txt , int offset , int length ) ; mcxstatus filterTxt ( filter* fd , mcxTing* txt , int offset , int length ) ; mcxstatus filterStrip ( filter* fd , mcxTing* txt , int offset , int length ) ; mcxstatus filterCopy ( filter* fd , mcxTing* txt , int offset , int length ) ; fltfnc flts[6] = { NULL , filterDevice , filterDevice , filterTxt , filterCopy , filterStrip } ; int ZOEM_FILTER_NONE = 0; int ZOEM_FILTER_DEFAULT= 1; int ZOEM_FILTER_DEVICE = 2; int ZOEM_FILTER_TXT = 3; int ZOEM_FILTER_COPY = 4; int ZOEM_FILTER_STRIP = 5; #define F_DEVICE "device filter (customize with \\special#1)" #define F_TXT "interprets [\\\\][\\~][\\,][\\|][\\}][\\{]" #define F_COPY "identity filter (literal copy)" void yamPutConstant ( filter* fd , const char* p , int l ) ; void yamSpecialPut ( filter* fd , unsigned int c ) ; /* @ literal at newline in text filter. * | \| in text filter. * . literal plain newline in text or copy filter. * % format newline in at scope. * + literal plain newline in at scope. * ~ literal plain newline in plain scope. * > als filtering aan staat en er een niet lege string gefilterd wordt. */ void yamputnl ( const char *c , FILE* fp ) ; void filterFree ( filter* fd ) { mcxFree(fd) ; } filter* filterNew ( FILE* fp ) { filter* fd = mcxAlloc(sizeof(filter), EXIT_ON_FAIL) ; fd->indent = 0 ; fd->n_newlines = 1 /* count of flushed newlines */ ; fd->n_spaces = 0 /* count of stacked spaces */ ; fd->doformat = 1 ; fd->level = 1 ; fd->fp = fp ; return fd ; } mcxstatus filterTxt ( filter* fd , mcxTing* txt , int offset , int length ) { int esc = 0 ; char* o = txt->str + offset ; char* z = o + length ; char* p ; FILE* fp /* fixme: should get default data. so, default data * should not be in stack. no use in having fd in * stack, as it is passed around. * Why not pass filedata around? then you must always, * and cannot rely on default value. */ ; fd = fd ? fd : sink_default_g->fd ; fp = fd->fp ; for (p=o;p= offset + length) { yamErr("filterTxt PBD", "scope error!") ; return STATUS_FAIL ; } fputs("\\@", fp) ; if ((uchar) p[0] == 'e') fputc('e', fp) ; while(--l && ++p) { if (*p == '\n') yamputnl("@l", fp) /* lit at nl in txt flt */ ; else fputc(*p, fp) ; } break ; } case '\\' : fputc('\\', fp) ; break ; case '|' : yamputnl("\\|", fp); break /* \| in txt flt */ ; case '-' : fputc('-', fp) ; break ; case '~' : fputc(' ', fp) ; break /* wsm */ ; case '{' : fputc('{', fp) ; break ; case '}' : fputc('}', fp) ; break ; case ',' : ; break ; case '\n' : ; break ; default : fputc(*p, fp) ; break ; } esc = 0 ; } else if (*p == '\\') esc = 1 ; else { if (*p == '\n') yamputnl("nl", fp) /* lit plain nl in txt flt */ ; else fputc(*p, fp) ; } } ; return STATUS_OK ; } mcxstatus filterStrip ( filter* fd , mcxTing* txt , int offset , int length ) { return STATUS_OK ; } mcxstatus filterCopy ( filter* fd , mcxTing* txt , int offset , int length ) { char* p ; FILE* fp ; fd = fd ? fd : sink_default_g->fd ; fp = fd->fp ; for (p=txt->str+offset;pstr+offset+length;p++) { if (*p == '\n') yamputnl("nl", fp) /* lit nl (anywhere) in copy flt */ ; else fputc(*p, fp) ; } return STATUS_OK ; } enum { F_MODE_ATnESC = 1 , F_MODE_AT , F_MODE_ESC , F_MODE_DEFAULT } ; int yamAtDirective ( filter* fd , char c ) { FILE* fp = fd->fp ; switch(c) { case 'N' : while (fd->n_newlines < 1) { fd->n_newlines++ ; yamputnl("@N", fp) /* '%' nl in at scope */ ; } fd->n_spaces = 0 /* flush spaces */ ; break ; case 'P' : while (fd->n_newlines < 2) { fd->n_newlines++ ; yamputnl("@P", fp) /* '%' nl in at scope */ ; } fd->n_spaces = 0 /* flush spaces */ ; break ; case 'I' : fd->indent++ ; break ; case 'J' : fd->indent = MCX_MAX(fd->indent-1, 0) ; break ; case 'n' : yamputnl("@n", fp) /* '%' nl in at scope */ ; fd->n_newlines++ /* yanl */ ; fd->n_spaces = 0 /* flush spaces */ ; break ; case 'S' : fd->n_spaces++ /* stack a space */ ; break ; case 's' : fputc(' ', fp) ; fd->n_spaces = 0 /* flush other spaces */ ; fd->n_newlines = 0 /* no longer at bol */ ; break ; case 't' : yamputc(fd, '\t', 1) ; break ; case 'C' : fd->indent = 0 ; break ; default : yamErr("yamAtDirective", "unsupported '%%' option <%c>", c) ; } return 1 ; } /* * We keep track of spaces and newlines. If we print by yamputc, * yamputc does that for us. If we print by fputc, we do it ourselves. * * we ignore *(txt->offset+length) (it will be '\0' or '}' or so). */ mcxstatus filterAt ( filter* fd , mcxTing* txt , int offset , int length ) { char* o = txt->str + offset ; char* z = o + length ; char* p = o ; const char* me = "filterAt" ; int fltmode = F_MODE_AT ; mcxbool xml_sentinel = FALSE ; while (p" , p ) ; return STATUS_FAIL ; case '&' : /* fixme; yamBlock? while(1) */ { int x = yamClosingCurly (txt, offset + p-o+1, NULL, RETURN_ON_FAIL) ; mcxTing* stuff ; if (x<0) { yamErr("filterAt PBD", "scope error!") ; return STATUS_FAIL ; } stuff = mcxTingNNew(p+2, x-1) ; if (yamDigest(stuff, stuff, NULL)) { yamErr(me, "AND scope did not parse") ; mcxTingFree(&stuff) ; return STATUS_FAIL ; } if (filterAt(fd, stuff, 0, stuff->len)) { yamErr(me, "AND scope did not filter") ; mcxTingFree(&stuff) ; return STATUS_FAIL ; } mcxTingFree(&stuff) ; p += x+1 ; } break ; case '+' : ; if ( p+3 >= z || p[1] != '{' || !isdigit((unsigned char) p[2]) || p[3] != '}' ) yamErr(me, "+ requires {k} syntax, k in 0-9") ; else fd->level = ((unsigned char) p[2]) - '0' ; p += 3 ; break ; case '~' : case '|' : case '-' : yamErr ( me , "zoem glyphs not allowed in at scope - found <\\%c>" , c ) ; return STATUS_FAIL ; case 'X' : xml_sentinel = TRUE ; break ; case 'w' : fd->doformat = 0 ; break ; case 'W' : fd->doformat = 1 ; break ; case 'N' : case 'n' : case 'P' : case 'p' : case 'C' : case 'J' : case 'I' : case 's' : case 'S' : if (xml_sentinel && !fd->doformat) NOTHING ; else yamAtDirective(fd, *p) ; break ; default : yamErr(me, "unknown escape <%c>", c) ; } fltmode = F_MODE_AT ; break ; case F_MODE_AT : switch(c) { case '\\' : fltmode = F_MODE_ATnESC ; break ; default : yamputc(fd, c, 1) ; } break ; ; } p++ ; } return STATUS_OK ; } mcxstatus filterDevice ( filter* fd , mcxTing* txt , int offset , int length ) { char* o = txt->str + offset ; char* z = o + length ; char* p = o ; const char* me = "filterDevice" ; int x ; int fltmode = F_MODE_DEFAULT ; fd = fd ? fd : sink_default_g->fd ; /* * we must enter me in this mode by design, and this deserves more * explanation. docme, unfbus. * */ while (p= offset + length) { yamErr(me, "PBD scope error?!") ; return STATUS_FAIL ; } /* *(txt->str+offset+(p-o)+x) == '}' */ if ((uchar) p[-1] == 'e') { if (filterAt(fd, ampersand, 0, 1)) return STATUS_FAIL ; if (filterAt(fd, txt, offset + p-o+1, x-1)) return STATUS_FAIL ; if (filterAt(fd, semicolon, 0, 1)) return STATUS_FAIL ; } else if (filterAt(fd, txt, offset + p-o+1, x-1)) return STATUS_FAIL ; p += x ; break ; case '*' : { int l = yamEOConstant(txt, offset + p-o) ; if (l<0 || offset+(p-o)+1+l > offset + length) { yamErr(me, "PBD const!") ; return STATUS_FAIL ; } yamPutConstant(fd, p, l) ; p += l ; break ; } case '}' : case '{' : case '\\' : yamputc(fd, c, 0) ; break ; case '~' : yamSpecialPut(fd, 256) ; break ; case '|' : yamSpecialPut(fd, 257) ; break ; case '-' : yamSpecialPut(fd, 258) ; break ; case ',' : case '\n' : break ; ; default : yamErr(me, "ignoring escape <\\%c>", c) ; yamputc(fd, '\\', 0) /* wsm */ ; yamputc(fd, c, 0) /* wsm */ ; break ; } fltmode = F_MODE_DEFAULT ; break ; case F_MODE_DEFAULT : switch(c) { case '\\' : fltmode = F_MODE_ESC ; break ; default : yamputc(fd, c, 0) /* wsm */ ; } break ; ; } ; p++ ; } if (fltmode == F_MODE_ESC && length == 1) yamErr(me, "skipping dangling backslash (resulting from \\!)") ; else if (fltmode == F_MODE_ESC) yamErr(me, "unexpected dangling backslash, please file bug report") ; return STATUS_OK ; } mcxTing* specialGet ( int level , unsigned int c ) { yamSpecial* spec = &specials[c] ; if (!level) return NULL ; while (--level && spec->up) spec = spec->up ; return spec->txt ; } void yamputc ( filter* fd , unsigned char c , int atcall ) { FILE* fp = fd->fp ; mcxTing* special = atcall || !specials[c].txt ? NULL : specialGet(fd->level, c) ; if (special && (c == ' ' || c == '\n')) { filterAt(fd, special, 0, special->len) /* we don't do bookkeeping or squashing on mapped nl's and sp's * perhaps we could do so, but a design is needed first. * * fixme what if we want indent for '\n' ? */ ; } else if (fd->doformat) { if (c == ' ') { if (!fd->n_newlines) fd->n_spaces++ /* do not stack spaces at bol */ ; } else if (c == '\n') { if (fd->n_newlines < 1) { fd->n_newlines++ /* yamputnl,yamputc,doformat: @/. lit nl in at or plain scope */ ; yamputnl(atcall ? "@l" : "nl", fp) ; } fd->n_spaces = 0 /* flush all spaces when newline */ ; } else { if (fd->n_newlines) /* \@{\S}foo -- the f passes through here */ { int i = 0 ; for (i=0;iindent;i++) fputc(' ', fp) ; fd->n_newlines = 0 ; fd->n_spaces = 0 ; } else if (fd->n_spaces) { fputc(' ', fp) ; fd->n_spaces = 0 ; } if (special) filterAt(fd, special, 0, special->len) ; else fputc(c, fp) ; } } else { if (c == '\n') fd->n_newlines++ /* note: we still output below. */ ; else fd->n_newlines = 0 ; if (c != ' ' && fd->n_spaces) fd->n_spaces = 0 , fputc(' ', fp) ; if (special) filterAt(fd, special, 0, special->len) ; else { int i = 0 ; if (c == '\n') { yamputnl(atcall ? "@L" : "NL" , fp) /* yamputnl,yamputc,dontformat: +/~ lit nl in at or plain scope */ /* fixmefixme: the output below should only be done in case * non-blank follows. */ ; for (i=0;iindent;i++) fputc(' ', fp) ; } else fputc(c, fp) /* wsm */ ; } } } void yamPutConstant ( filter* fd , const char* p /* p[0] == '*' */ , int l ) { mcxTing* txt ; int delta = p[1] == '{' ? 2 : 1 ; static long n_star_deprecated = 0 ; mcxTingNWrite(zconstant, p+delta, l-delta) ; txt = yamConstantGet(zconstant) ; if (txt) filterAt(fd, txt, 0, txt->len) ; else yamErr("yamPutConstant", "warning: constant *%s* not found", zconstant->str) ; if (delta == 1 && !n_star_deprecated++) yamErr ( "zoem" , "deprecated: \\*%s*, use \\*{%s} instead" , zconstant->str , zconstant->str ) ; } void yamSpecialPut ( filter* fd , unsigned int c ) { mcxTing* spc = specialGet(fd->level, c) ; if (c < N_SPECIAL && spc) filterAt(fd, spc, 0, spc->len) ; } void yamSpecialSet ( long c , const char* str ) { if (c < 0) c *= -1 , c += 255 ; if (c >= N_SPECIAL) return ; if (!specials[c].txt) specials[c].txt = mcxTingNew(str) ; else { yamSpecial* spec = &specials[c] ; while (spec->up) spec = spec->up ; spec->up = mcxAlloc(sizeof(yamSpecial), EXIT_ON_FAIL) ; spec->up->txt = mcxTingNew(str) ; spec->up->up = NULL ; } ; } void yamSpecialClean ( void ) { int i ; for (i=0;iup ; mcxTingFree(&spec->txt) ; if (spec != &specials[i]) mcxFree(spec) ; else spec->txt = NULL , spec->up = NULL ; spec = up ; } } ; } void mod_filter_exit ( void ) { yamSpecialClean() ; mcxTingFree(&zconstant) ; mcxTingFree(&ersand) ; mcxTingFree(&semicolon) ; } void mod_filter_init ( int n ) { int i ; for (i=0;in_newlines < 1) { fputc('\n', fp) ; fd->n_newlines++ ; } } void filterSetFP ( filter* fd , FILE* fp ) { fd->fp = fp ; } zoem-11-166/src/key.c0000644000402500021140000002234511330317152011220 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * (C) Copyright 2008, 2009 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include #include #include #include #include #include "key.h" #include "dict.h" #include "sink.h" #include "read.h" #include "util.h" #include "util/ting.h" #include "util/io.h" #include "util/minmax.h" #include "util/types.h" #include "util/array.h" #include "util/hash.h" /* , __$args__ , __$xargs__ ! __sysval__ ! __zoemput__ ! __zoemstat__ */ const char *strSession[] = { "\\$__args__ (local to env) key/value pairs given to \\begin#2" , "\\$__xargs__ (local to env) key/value pairs given to \\begin#2, expanded" , "\\__device__ name of device (given by -d)" , "\\__fnbase__ base name of entry file (given by -i/-I)" , "\\__fnentry__ name of entry file (given by -i/-I)" , "\\__fnin__ name of current input file" , "\\__fnout__ name of current output file" , "\\__fnpath__ path component of entry file (given by -i/-I)" , "\\__fnwrite__ arg1 to \\write#3, accessible in arg3 scope" , "\\__lc__ expands to a left curly (only for magic)" , "\\__line__ index of current input line" , "\\__parmode__ paragraph slurping mode for interactive sessions" , "\\__rc__ expands to a right curly (only for magic)" , "\\__searchpath__ search path for macro packages (e.g. man.zmm)" , "\\__split__ user space toggle for chapter mode indicator" , "\\__sysval__ exit status of last system command" , "\\__version__ version of zoem, formatted as e.g. 2003, 2004-010" , "\\__zoemput__ result text of last \\try#1 key" , "\\__zoemstat__ status of last \\try#1 key" , NULL } ; static dictStack* usrstack = NULL; static dim n_user_override = 0; mcxstatus usrDictPop ( const char* label ) { return dictStackPop(usrstack, "user", label) ; } mcxstatus usrDictPush ( const char* label ) { return dictStackPush(usrstack, 16, label) ; } void yamKeyList ( const char* mode ) { mcxbool listAll = strstr(mode, "all") != NULL ; if (listAll || strstr(mode, "session")) { int m ; fputs("\nPredefined session variables\n", stdout) ; for (m=0;strSession[m];m++) fprintf(stdout, "%s\n", strSession[m]) ; } ; } void yamKeySet ( const char* key , const char* val ) { mcxTing* keytxt = mcxTingNew(key) ; if (yamKeyInsert(keytxt, val, strlen(val), 0, NULL) != keytxt) mcxTingFree(&keytxt) ; } void yamKeyDef ( const char* key , const char* val ) { mcxTing* keytxt = mcxTingNew(key) ; if (yamKeyInsert(keytxt, val, strlen(val), 0, NULL) != keytxt) { yamErr("yamKeyDef", "overwriting key <%s> (now %s)", keytxt->str, val) ; mcxTingFree(&keytxt) ; } } mcxKV* yamKVgetx ( mcxTing* key , const mcxTing* dict_name , mcxbits bits ) { keyDict *dict = usrstack->top ; mcxenum DATUM_MODE = bits & YAM_SET_EXISTING ? MCX_DATUM_FIND : MCX_DATUM_INSERT ; mcxKV* kv = NULL ; int n_dict_ok = 0 /* number of matching dictionaries */ ; mcxbool dollar = (unsigned char) key->str[0] == '$' ; if (dollar) dict = sinkGetDLRtop() ; else if (bits & YAM_SET_GLOBAL) dict = usrstack->bottom ;if(0)fprintf(stderr, "hey!\n") ; while (dict) { int dict_ok = !dict_name || !strcmp(dict_name->str, dict->name->str) ; n_dict_ok += dict_ok ; if (dict_ok && (kv = mcxHashSearch(key, dict->table, DATUM_MODE))) break ; dict = dict->down ; } if (!kv && dollar) { dict = sinkGetDLRdefault() ;if(0)fprintf(stderr, "hi!\n") ; while (dict) { if (dict_name && strcmp(dict_name->str, dict->name->str)) do { } while (0) ; else if ((kv = mcxHashSearch(key, dict->table, DATUM_MODE))) break ; dict = dict->down ; } } if (dict_name && !n_dict_ok) yamErr ( "\\set#3" , "%s dictionary <%s> not found" , dollar ? "dollar" : "user" , dict_name->str ) ; else if (bits & YAM_SET_EXISTING && !kv) yamErr("\\set#3", "key <%s> does not exist", key->str) ; return kv ; } mcxKV* yamKVget ( mcxTing* key ) { keyDict *dict = (unsigned char) key->str[0] == '$' ? sinkGetDLRtop() : usrstack->top ; mcxKV* kv = NULL ; while (dict) { if ((kv = mcxHashSearch(key, dict->table, MCX_DATUM_FIND))) break ; dict = dict->down ; } if (!kv && (unsigned char) key->str[0] == '$') { dict = sinkGetDLRdefault() ; while (dict) { if ((kv = mcxHashSearch(key, dict->table, MCX_DATUM_FIND))) break ; dict = dict->down ; } } ;if (kv && !kv->val) fprintf(stderr, "Odd: no value for key %s\n", key->str); return kv ; } mcxTing* yamKeyInsert ( mcxTing* key , const char* valstr , dim vallen , mcxbits bits , const mcxTing* dict_name ) { mcxKV* kv = NULL ; mcxbool scope_env = (unsigned char) key->str[0] == '$' ; if ((bits & YAM_SET_EXISTING) || dict_name) kv = yamKVgetx(key, dict_name, bits & (YAM_SET_EXISTING | YAM_SET_GLOBAL)) ; else { keyDict *dict = scope_env ? sinkGetDLRtop() : bits & YAM_SET_GLOBAL ? usrstack->bottom : usrstack->top ; kv = mcxHashSearch ( key , dict->table , MCX_DATUM_INSERT ) ; } if (kv) { if (!kv->val) kv->val = mcxTingNNew(valstr, vallen) ; else if (bits & YAM_SET_APPEND) mcxTingNAppend((mcxTing*) (kv->val), valstr, vallen) ; else if (!(bits & YAM_SET_COND)) mcxTingNWrite((mcxTing*) (kv->val), valstr, vallen) ; } return kv ? kv->key : NULL ; } mcxbool yamKeyDeletex ( const char* key ) { mcxTing* deletee = yamKeyDelete(key, FALSE) ; mcxbool found = deletee ? TRUE : FALSE ; mcxTingFree(&deletee) ; return found ; } mcxTing* yamKeyDelete ( const char* keystr , mcxbool global ) { mcxTing* key = mcxTingNew(keystr) ; keyDict *dict = global ? usrstack->bottom : keystr[0] == '$' ? sinkGetDLRtop() : usrstack->top ; mcxKV* kv = (mcxKV*) mcxHashSearch ( key , dict->table , MCX_DATUM_DELETE ) ; mcxTingFree(&key) ; if (kv) { mcxTing* kvval = kv->val ; mcxTing* kvkey = kv->key ; mcxTingFree(&kvkey) ; return kvval ; } return NULL ; } mcxTing* yamKeyGetGlobal ( mcxTing* key ) { keyDict *dict = usrstack->bottom ; mcxKV* kv = (mcxKV*) mcxHashSearch ( key , dict->table , MCX_DATUM_FIND ) ; if (kv) return (mcxTing*) kv->val ; return NULL ; } mcxTing* yamKeyGetLocal ( mcxTing* key ) { keyDict *dict = *(key->str) == '$' ? sinkGetDLRtop() : usrstack->top ; mcxKV* kv = (mcxKV*) mcxHashSearch ( key , dict->table , MCX_DATUM_FIND ) ; if (kv) return (mcxTing*) kv->val ; return NULL ; } mcxTing* yamKeyGetByDictName ( mcxTing* dict_name , mcxTing* key ) { keyDict *dict = usrstack->top ; mcxKV* kv = NULL ; mcxbool dollar = (unsigned char) key->str[0] == '$' ; if (dollar) dict = sinkGetDLRtop() ; while (dict) { if ( !strcmp(dict_name->str, dict->name->str) && (kv = mcxHashSearch(key, dict->table, MCX_DATUM_FIND)) ) break ; dict = dict->down ; } if (!kv && dollar) { dict = sinkGetDLRdefault() ; while (dict) { if(0)fprintf(stderr, "search dict %s\n", dict->name->str) ; if ( !strcmp(dict_name->str, dict->name->str) && (kv = mcxHashSearch(key, dict->table, MCX_DATUM_FIND)) ) break ; dict = dict->down ; } } ; return kv ? kv->val : NULL ; } mcxTing* yamKeyGet ( mcxTing* key ) { mcxKV* kv = yamKVget(key) ; return kv ? kv->val : NULL ; } void mod_key_exit ( void ) { mcxTing* ting = mcxTingNew("__fnout__") ; mcxTing* fnout = yamKeyGet(ting) /* fnout is written in bottom-level dictionary, * so dictStackFree may only use third argument * /before/ it frees that dictionary. */ ; dictStackFree(&usrstack, "user", fnout ? fnout->str : "panic") ; mcxTingFree(&ting) ; } void mod_key_init ( dim dict_size ) { dim n_max = n_user_override > 0 ? n_user_override : 100 ; usrstack = dictStackNew(dict_size, n_max, "''") ; } void yamKeyStats ( void ) { mcxHashStats(stdout, usrstack->bottom->table) ; } void keyULimit ( dim n_user ) { n_user_override = n_user; ; } zoem-11-166/src/dict.c0000644000402500021140000000647011330320016011345 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include #include /* fileno too */ #include #include #include #include "dict.h" #include "util.h" #include "util/ting.h" #include "util/types.h" #include "util/alloc.h" #include "util/hash.h" void dictStackFree ( dictStack** stackpp , const char* type , const char* fname ) { dictStack* stack = *stackpp ; keyDict* dict = stack->top ; keyDict* next /* delta is because the bottom user dictionary is put * in place by zoem and is beyond control of the user */ ; while (dict) { next = dict->down ; if (dict->level > 1) yamErr ( "dictStackFree" , "%s dictionary <%s> not closed in output file <%s>" , type , dict->name->str , fname ) ; mcxHashFree(&dict->table, mcxTingRelease, mcxTingRelease) ; mcxTingFree(&dict->name) ; mcxFree(dict) ; dict = next ; } free(stack) ; *stackpp = NULL ; } dictStack* dictStackNew ( dim dict_size , dim n_dict_max , const char* name ) { keyDict* dict = mcxAlloc(sizeof(keyDict), EXIT_ON_FAIL) ; dictStack* stack = mcxAlloc(sizeof *stack, EXIT_ON_FAIL) ; dict->down = NULL ; dict->name = mcxTingNew(name) ; dict->table = yamHashNew(dict_size) ; mcxHashSetOpts(dict->table, 0.25, -1) ; stack->top = dict ; stack->bottom = dict ; stack->n_dict = 1 ; stack->N_dict = n_dict_max ; dict->level = stack->n_dict ; return stack ; } mcxstatus dictStackPush ( dictStack* stack , int dict_size , const char* label ) { keyDict* top ; if (stack->n_dict+1 > stack->N_dict) { yamErr ( "dictStackPush" , "no more than <%d> dicts allowed in stack" , stack->N_dict ) ; return STATUS_FAIL ; } top = mcxAlloc(sizeof(keyDict), EXIT_ON_FAIL) ; top->down = stack->top ; top->table = yamHashNew(dict_size) ; top->name = mcxTingNew(label) ; top->level = stack->n_dict + 1 ; stack->top = top ; stack->n_dict++ ; return STATUS_OK ; } mcxstatus dictStackPop ( dictStack* stack , const char* type , const char* name ) { keyDict* top = stack->top ; if (!top->down) { yamErr ( "dictStackPop" , "cannot pop last <%s> scope!" , type , top->name->str ) ; return STATUS_FAIL ; } else if (strcmp(name, top->name->str)) { yamErr ( "dictStackPop" , "close request for <%s> while <%s> in scope" , name , top->name->str ) ; return STATUS_FAIL ; } mcxHashFree(&(top->table), mcxTingRelease, mcxTingRelease) ; mcxTingFree(&(top->name)) ; stack->top = top->down ; mcxFree(top) ; stack->n_dict-- ; return STATUS_OK ; } zoem-11-166/src/ops.c0000644000402500021140000025422211574411452011242 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ /* TODO * inspect#4 is bugly and uggy. */ #include "ops.h" #include #include #include #include #include #include #include #include #include "ops-xtag.h" #include "ops-grape.h" #include "ops-constant.h" #include "ops-env.h" #include "op-inspect.h" #include "op-format.h" #include "util.h" #include "digest.h" #include "key.h" #include "filter.h" #include "sink.h" #include "source.h" #include "segment.h" #include "parse.h" #include "read.h" #include "curly.h" #include "iface.h" #include "util/ting.h" #include "util/ding.h" #include "util/hash.h" #include "util/io.h" #include "util/minmax.h" #include "util/rand.h" #include "util/err.h" #include "util/types.h" #include "util/tr.h" #include "util/let.h" #include "util/minmax.h" #include "util/compile.h" static double precision_g = 1e-8; long roundnear (double f) { return (long) floor(f + 0.5) ; } #define arg(ting) mcxTingNNew(ting->str, ting->len) #define I_BANG_1 "{any}" #define J_BANG_1 "strip curlies, put any" #define I_DONE_0 "" #define J_DONE_0 "quit current stack (use at file level)" #define I_BANG_0 "" #define J_BANG_0 "make slash" #define I_XTAG_1 "{_any_}" #define J_XTAG_1 "xml tag sugar" #define I_XTAG_2 "{_any_}{_any_}" #define J_XTAG_2 "xml tag+content sugar" #define I_DEF_2 "{ks}{any}" #define J_DEF_2 "define key; complain if key exists" #define I_FORMAT_2 "{syn}{_va_}" #define J_FORMAT_2 "format varargs according to format syntax" #define I_DEFX_2 "{ks}{_any_}" #define J_DEFX_2 "define key; expand before storing" #define I_LET_1 "{algebra}" #define J_LET_1 "evaluate arithmetic expression" #define I_VANISH_1 "{any}" #define J_VANISH_1 "process any for side effects only" #define I_TRY_1 "{any}" #define J_TRY_1 "write status/result in __zoemstat__/__zoemput__" #define I_SET_2 "{ks}{any}" #define J_SET_2 "do not complain if key exists" #define I_SET_3 "{{modes}{acgltuvwx}}{ks}{any}" #define J_SET_3 "set key with access to all modes" #define I_SETX_2 "{ks}{_any_}" #define J_SETX_2 "expand definition before storing" #define I_THROW_2 "{error|towel}{_any_}" #define J_THROW_2 "throw error/towell, print msg _any_" #define I_REGISTER_2 "{tag}{any}" #define J_REGISTER_2 "register any with tag (e.g. END)" #define I_TEXTMAP_2 "{va}{_any_}" #define J_TEXTMAP_2 "apply va-encoded map to any" #define I_APPLY_2 "{_ks|ak_}{_va_}" #define J_APPLY_2 "apply (possibly anon) key ex to vararg" #define I_LENGTH_1 "{_any_}" #define J_LENGTH_1 "evaluate and put length in place" #define I_WHILST_2 "{_int_}{_any_}" #define J_WHILST_2 "eval and output any while int nonzero" #define I_WHILE_2 "{_int_}{_any_}" #define J_WHILE_2 "eval any while int nonzero" #define I_DOWHILE_2 "{_any_}{_int_}" #define J_DOWHILE_2 "eval any until int nonzero" #define I_TABLE_5 "{_int_}{lft}{sep}{rgt}{_va_}" #define J_TABLE_5 "create array-like structure" #define I_SYSTEM_3 "{cmd}{_va_}{_any_}" #define J_SYSTEM_3 "pipe any through cmd with arguments va" #define I_ENV_4 "{lbl}{any}{any}{any}" #define J_ENV_4 "associate strings with env lbl" #define I_BEGIN_2 "{lbl}{va}" #define J_BEGIN_2 "begin env with args" #define I_END_1 "{lbl}" #define J_END_1 "end env" #define I_TRACE_1 "{_int_}" #define J_TRACE_1 "set trace flags" #define I_WRITE_3 "{_fn_}{nm}{_any_}" #define J_WRITE_3 "write any via filter nm (copy|txt|device) to file" #define I_DOFILE_2 "{_fn_}{chr(!?)chr(+-)}" #define J_DOFILE_2 "read file with input/existence modes" #define I_PROTECT_1 "{_any_}" #define J_PROTECT_1 "escape contents" #define I_FINSERT_1 "{_fn_}" #define J_FINSERT_1 "put escaped contents in place" #define I_NARGS_1 "{any}" #define J_NARGS_1 "count number of scopes in any" #define I_ZINSERT_1 "{_fn_}" #define J_ZINSERT_1 "put unmodified contents in place" #define I_INSPECT_4 "{_va_}{_reg_}{_any|ak_}{_any_}" #define J_INSPECT_4 "apply regex to any" #define I_TR_2 "{chr(cds)*{list}{list}}{_any_}" #define J_TR_2 "translate chars in any" #define I_LINE_0 "" #define J_LINE_0 "put current line number in current file" #define I_REDIRECT_1 "{_fn_}" #define J_REDIRECT_1 "change default output file" #define I_QUIT_0 "" #define J_QUIT_0 "quit parsing current stack in current file" #define I_ERROR_1 "_any_" #define J_ERROR_1 "expand any, print error message, raise error" #define I_EVAL_1 "_any_" #define J_EVAL_1 "expand any, pass it on for further expansion" #define I_EXIT_0 "" #define J_EXIT_0 "out through the door without opening it" #define I_PUSH_1 "{user|dollar}" #define J_PUSH_1 "push a new dollar/user dictionary" #define I_GET_2 "{dict-name}{ks}" #define J_GET_2 "retrieve key from named dictionary" #define I_POP_1 "{user|dollar}" #define J_POP_1 "pop the top dollar/user dictionary" #define I_FV_2 "{nm}{_va_}" #define J_FV_2 "apply operator nm to ops" #define I_F_3 "{nm}{_num_}{_num_}" #define J_F_3 "apply operator nm to ops" #define I_F_2 "{nm}{_num_}" #define J_F_2 "apply operator nm to op" #define I_CMP_3 "{nm}{_any_}{_any_}" #define J_CMP_3 "apply nm (lt|lq|eq|gq|gt|ne|cp) to ops; put int" #define I_EQT_3 "{nm}{_num_}{_num_}" #define J_EQT_3 "apply nm (lt|lq|eq|gq|gt|ne|cp) to ops; put int" #define I_IF_3 "{_int_}{any}{any}" #define J_IF_3 "if int any else any" #define I_DEFINED_2 "{nm}{_any_}" #define J_DEFINED_2 "test for (key|lkey|data|primitive|builtin|zoem|ENV)" #define I_UNDEF_1 "{ks}" #define J_UNDEF_1 "delete key" #define I_SWITCH_2 "{_any_}{va}" #define J_SWITCH_2 "use pivot to select from va" #define I_BRANCH_1 "{va}" #define J_BRANCH_1 "va contains condition/branch pairs" #define I_DSET_2 "{_any|va_}{any|va}" #define J_DSET_2 "access sequence, value or values" #define I_DSETX_2 "{_any|va_}{_any|va_}" #define J_DSETX_2 "access sequence, value or values" #define I_GRAPE1_1 "{_any|va_}" #define J_GRAPE1_1 "access sequence for getting" #define I_GRAPE2_1 "{_any|va_}" #define J_GRAPE2_1 "access sequence for freeing" #define I_GRAPE3_1 "{_any|va_}" #define J_GRAPE3_1 "access sequence for dumping" #define I_DFREE_1 "{_any|va_}" #define J_DFREE_1 "access sequence" #define I_DPRINT_1 "{_any|va_}" #define J_DPRINT_1 "access sequence" #define I_SPECIAL_1 "{va}" #define J_SPECIAL_1 "pairs of ascii num/mapping" #define I_CONSTANT_1 "{va}" #define J_CONSTANT_1 "pairs of label/mapping" #define I_CATCH_2 "{towel|error}{any}" #define J_CATCH_2 "catch exception=towel and/or error" #define I_DOLLAR_2 "{str}{any}" #define J_DOLLAR_2 "put any if \\__device__==str" #define I_FORMATTED_1 "{any}" #define J_FORMATTED_1 "remove ws in any, translate \\%nst<>%" #define F_DEVICE "device filter (customize with \\special#1)" #define F_TXT "interprets [\\\\][\\~][\\,][\\|][\\}][\\{]" #define F_COPY "identity filter (literal copy)" const char *strLegend[] = { "" "L e g e n d", "Ab Meaning Examples/explanation", "--| |----------------| |---------------------------------------------------|", "ak anonymous key e.g. <_#2{foo{\\1}\\bar{\\1}{\\2}}>", "any anything anything", "chr character presumably a switch of some kind", "fn file name a string that will be used as name of file", "int integer e.g. '123', '-6', no arithmetic expressions allowed", "ks key signature e.g. or <\"+\"#2> (without the <>)", "lbl label names for constants, env", "nm name name; one of a fixed set", "str string presumably a label of some kind", "syn syntax argument satisfies special syntax", "va vararg of the form {any1} {any2} {any3}", "", "[]-enclosed stuff is optional", "()-enclosed stuff denotes a choice between alternatives", "* denotes zero or more occurrences", "_-enclosed arguments are first expanded by the primitive.", "So, _int_ denotes an arbitrary expression that should evaluate to an integer", NULL } ; static mcxHash* yamTable_g = NULL; /* primitives */ static mcxTing* devtxt_g = NULL; /* "__device__" */ static mcxLink* reg_end_g = NULL; typedef struct { const char* name ; const char* tag ; const char* descr ; yamSeg* (*yamfunc)(yamSeg* seg) /* either this */ ; const char* composite /* or that but not both */ ; } cmdHook ; yamSeg* expandBang1 ( yamSeg* seg) ; yamSeg* expandBang2 ( yamSeg* seg) ; yamSeg* expandXtag1 ( yamSeg* seg) ; yamSeg* expandXtag2 ( yamSeg* seg) ; yamSeg* expandDollar2 ( yamSeg* seg) ; yamSeg* expandGrapeDump ( yamSeg* seg) ; yamSeg* expandGrapeFree ( yamSeg* seg) ; yamSeg* expandGrapeGet ( yamSeg* seg) ; yamSeg* expandApply2 ( yamSeg* seg) ; yamSeg* expandBegin2 ( yamSeg* seg) ; yamSeg* expandBranch1 ( yamSeg* seg) ; yamSeg* expandCatch2 ( yamSeg* seg) ; yamSeg* expandCmp3 ( yamSeg* seg) ; yamSeg* expandConstant1 ( yamSeg* seg) ; yamSeg* expandDef2 ( yamSeg* seg) ; yamSeg* expandDefined2 ( yamSeg* seg) ; yamSeg* expandDefx2 ( yamSeg* seg) ; yamSeg* expandDofile2 ( yamSeg* seg) ; yamSeg* expandDowhile2 ( yamSeg* seg) ; yamSeg* expandDprint1 ( yamSeg* seg) ; yamSeg* expandEnd1 ( yamSeg* seg) ; yamSeg* expandEnv4 ( yamSeg* seg) ; yamSeg* expandEqt3 ( yamSeg* seg) ; yamSeg* expandEval1 ( yamSeg* seg) ; yamSeg* expandExit0 ( yamSeg* seg) ; yamSeg* expandF2 ( yamSeg* seg) ; yamSeg* expandF3 ( yamSeg* seg) ; yamSeg* expandFinsert1 ( yamSeg* seg) ; yamSeg* expandFormat2 ( yamSeg* seg) ; yamSeg* expandFormatted1( yamSeg* seg) ; yamSeg* expandFv2 ( yamSeg* seg) ; yamSeg* expandGet2 ( yamSeg* seg) ; yamSeg* expandIf3 ( yamSeg* seg) ; yamSeg* expandInspect4 ( yamSeg* seg) ; yamSeg* expandJumpLc1 ( yamSeg* seg) ; yamSeg* expandLength1 ( yamSeg* seg) ; yamSeg* expandLet1 ( yamSeg* seg) ; yamSeg* expandLine ( yamSeg* seg) ; yamSeg* expandSHenv ( yamSeg* seg) ; yamSeg* expandNargs1 ( yamSeg* seg) ; yamSeg* expandPop1 ( yamSeg* seg) ; yamSeg* expandProtect1 ( yamSeg* seg) ; yamSeg* expandPush1 ( yamSeg* seg) ; yamSeg* expandWriteto1 ( yamSeg* seg) ; yamSeg* expandRegister2 ( yamSeg* seg) ; yamSeg* expandSet2 ( yamSeg* seg) ; yamSeg* expandSet3 ( yamSeg* seg) ; yamSeg* expandSetx2 ( yamSeg* seg) ; yamSeg* expandSpecial1 ( yamSeg* seg) ; yamSeg* expandSwitch2 ( yamSeg* seg) ; yamSeg* expandSystem3 ( yamSeg* seg) ; yamSeg* expandTable5 ( yamSeg* seg) ; yamSeg* expandTest3 ( yamSeg* seg) ; yamSeg* expandTestFile2 ( yamSeg* seg) ; yamSeg* expandTextmap2 ( yamSeg* seg) ; yamSeg* expandThrow2 ( yamSeg* seg) ; yamSeg* expandTr2 ( yamSeg* seg) ; yamSeg* expandTrace1 ( yamSeg* seg) ; yamSeg* expandTry1 ( yamSeg* seg) ; yamSeg* expandUndef1 ( yamSeg* seg) ; yamSeg* expandVanish1 ( yamSeg* seg) ; yamSeg* expandWhile2 ( yamSeg* seg) ; yamSeg* expandWhilst2 ( yamSeg* seg) ; yamSeg* expandWrite3 ( yamSeg* seg) ; yamSeg* expandZinsert1 ( yamSeg* seg) ; static cmdHook cmdHookDir[] = { { "!#1" , I_BANG_0 , J_BANG_0 , expandBang1 , NULL } , { "!#2" , I_BANG_1 , J_BANG_1 , expandBang2 , NULL } , { "$#2" , I_DOLLAR_2 , J_DOLLAR_2 , expandDollar2 , NULL } , { "%#1" , I_GRAPE1_1 , J_GRAPE1_1 , expandGrapeGet , NULL } , { "%free#1" , I_GRAPE2_1 , J_GRAPE2_1 , expandGrapeFree , NULL } , { "%dump#1" , I_GRAPE3_1 , J_GRAPE3_1 , expandGrapeDump , NULL } , { "<>#1" , I_XTAG_1 , J_XTAG_1 , expandXtag1 , NULL } , { "<>#2" , I_XTAG_2 , J_XTAG_2 , expandXtag2 , NULL } , { "apply#2" , I_APPLY_2 , J_APPLY_2 , expandApply2 , NULL } , { "begin#2" , I_BEGIN_2 , J_BEGIN_2 , expandBegin2 , NULL } , { "branch#1" , I_BRANCH_1 , J_BRANCH_1 , expandBranch1 , NULL } , { "catch#2" , I_CATCH_2 , J_CATCH_2 , expandCatch2 , NULL } , { "cmp#3" , I_CMP_3 , J_CMP_3 , expandCmp3 , NULL } , { "constant#1" , I_CONSTANT_1 , J_CONSTANT_1 , expandConstant1 , NULL } , { "def#2" , I_DEF_2 , J_DEF_2 , expandDef2 , NULL } , { "defined#2" , I_DEFINED_2 , J_DEFINED_2 , expandDefined2 , NULL } , { "defx#2" , I_DEFX_2 , J_DEFX_2 , expandDefx2 , NULL } , { "dofile#2" , I_DOFILE_2 , J_DOFILE_2 , expandDofile2 , NULL } #if 0 , { "done" , I_DONE_0 , J_DONE_0 , expandDone0 , NULL } #endif , { "dowhile#2" , I_DOWHILE_2 , J_DOWHILE_2 , expandDowhile2 , NULL } , { "end#1" , I_END_1 , J_END_1 , expandEnd1 , NULL } , { "env#4" , I_ENV_4 , J_ENV_4 , expandEnv4 , NULL } , { "eqt#3" , I_EQT_3 , J_EQT_3 , expandEqt3 , NULL } , { "eval#1" , I_EVAL_1 , J_EVAL_1 , expandEval1 , NULL } , { "exit" , I_EXIT_0 , J_EXIT_0 , expandExit0 , NULL } , { "f#2" , I_F_2 , J_F_2 , expandF2 , NULL } , { "f#3" , I_F_3 , J_F_3 , expandF3 , NULL } , { "finsert#1" , I_FINSERT_1 , J_FINSERT_1 , expandFinsert1 , NULL } , { "format#2" , I_FORMAT_2 , J_FORMAT_2 , expandFormat2 , NULL } , { "formatted#1", I_FORMATTED_1 , J_FORMATTED_1 , expandFormatted1 , NULL } , { "fv#2" , I_FV_2 , J_FV_2 , expandFv2 , NULL } , { "get#2" , I_GET_2 , J_GET_2 , expandGet2 , NULL } , { "if#3" , I_IF_3 , J_IF_3 , expandIf3 , NULL } , { "inspect#4" , I_INSPECT_4 , J_INSPECT_4 , expandInspect4 , NULL } , { "length#1" , I_LENGTH_1 , J_LENGTH_1 , expandLength1 , NULL } , { "let#1" , I_LET_1 , J_LET_1 , expandLet1 , NULL } , { "nargs#1" , I_NARGS_1 , J_NARGS_1 , expandNargs1 , NULL } , { "pop#1" , I_POP_1 , J_POP_1 , expandPop1 , NULL } , { "protect#1" , I_PROTECT_1 , J_PROTECT_1 , expandProtect1 , NULL } , { "push#1" , I_PUSH_1 , J_PUSH_1 , expandPush1 , NULL } , { "register#2" , I_REGISTER_2 , J_REGISTER_2 , expandRegister2 , NULL } , { "set#2" , I_SET_2 , J_SET_2 , expandSet2 , NULL } , { "set#3" , I_SET_3 , J_SET_3 , expandSet3 , NULL } , { "setx#2" , I_SETX_2 , J_SETX_2 , expandSetx2 , NULL } , { "special#1" , I_SPECIAL_1 , J_SPECIAL_1 , expandSpecial1 , NULL } , { "switch#2" , I_SWITCH_2 , J_SWITCH_2 , expandSwitch2 , NULL } , { "system#3" , I_SYSTEM_3 , J_SYSTEM_3 , expandSystem3 , NULL } , { "table#5" , I_TABLE_5 , J_TABLE_5 , expandTable5 , NULL } , { "textmap#2" , I_TEXTMAP_2 , J_TEXTMAP_2 , expandTextmap2 , NULL } , { "throw#2" , I_THROW_2 , J_THROW_2 , expandThrow2 , NULL } , { "tr#2" , I_TR_2 , J_TR_2 , expandTr2 , NULL } , { "trace#1" , I_TRACE_1 , J_TRACE_1 , expandTrace1 , NULL } , { "try#1" , I_TRY_1 , J_TRY_1 , expandTry1 , NULL } , { "undef#1" , I_UNDEF_1 , J_UNDEF_1 , expandUndef1 , NULL } , { "vanish#1" , I_VANISH_1 , J_VANISH_1 , expandVanish1 , NULL } , { "while#2" , I_WHILE_2 , J_WHILE_2 , expandWhile2 , NULL } , { "whilst#2" , I_WHILST_2 , J_WHILST_2 , expandWhilst2 , NULL } , { "write#3" , I_WRITE_3 , J_WRITE_3 , expandWrite3 , NULL } , { "writeto#1" , I_REDIRECT_1 , J_REDIRECT_1 , expandWriteto1 , NULL } , { "zinsert#1" , I_ZINSERT_1 , J_ZINSERT_1 , expandZinsert1 , NULL } , { "___jump_lc___#1", NULL , NULL , expandJumpLc1 , NULL } , { "__line__" , NULL , NULL , expandLine , NULL } , { "__env__#1" , NULL , NULL , expandSHenv , NULL } , { "__test__#3" , NULL , NULL , expandTest3 , NULL } , { "testfile#2" , NULL , NULL , expandTestFile2 , NULL } , { "done" , NULL , NULL , NULL , "\\'throw{done}" } , { "ifdef#3" , NULL , NULL , NULL , "\\'if{\\defined{\\1}{\\2}}{\\3}{}" } , { "ifdef#4" , NULL , NULL , NULL , "\\'if{\\defined{\\1}{\\2}}{\\3}{\\4}" } , { "input#1" , NULL , NULL , NULL , "\\'dofile{\\1}{!+}" } , { "import#1" , NULL , NULL , NULL , "\\'dofile{\\1}{!-}" } , { "read#1" , NULL , NULL , NULL , "\\'dofile{\\1}{?+}" } , { "load#1" , NULL , NULL , NULL , "\\'dofile{\\1}{?-}" } , { "begin#1" , NULL , NULL , NULL , "\\'begin{\\1}{}" } , { "env#3" , NULL , NULL , NULL , "\\'env{\\1}{}{\\2}{\\3}" } , { "system#2" , NULL , NULL , NULL , "\\'system{\\1}{\\2}{}" } , { "system#1" , NULL , NULL , NULL , "\\'system{\\1}{}{}" } , { "throw#1" , NULL , NULL , NULL , "\\'throw{\\1}{}" } , { "inform#1" , NULL , NULL , NULL , "\\'write{stderr}{device}{\\1\\@{\\N}}" } , { "append#2" , NULL , NULL , NULL , "\\'set{{modes}{a}}{\\1}{\\2}" } , { "appendx#2" , NULL , NULL , NULL , "\\'set{{modes}{ax}}{\\1}{\\2}" } , { "seq#4" , NULL , NULL , NULL , "\\'set{\\1}{\\2}\\'while{\\'let{\\'get{''}{\\1}<\\3}}{\\4\\'setx{\\1}{\\'let{\\'get{''}{\\1}+1}}}" } , { "update#2" , NULL , NULL , NULL , "\\'set{{modes}{e}}{\\1}{\\2}" } , { "updatex#2" , NULL , NULL , NULL , "\\'set{{modes}{ex}}{\\1}{\\2}" } , { "\"\"" , NULL , NULL , NULL , "" } , { "\"\"#1" , NULL , NULL , NULL , "" } , { "group#1" , NULL , NULL , NULL , "\\1" } , { "PI" , NULL , NULL , NULL , "3.1415926536" } , { "E" , NULL , NULL , NULL , "2.71828182846" } , { "$#1" , NULL , NULL , NULL , "\\'switch{\\__device__}{\\1}" } , { "$#3" , NULL , NULL , NULL , "\\'switch{\\__device__}{{\\1}{\\2}{\\3}}" } , { NULL , NULL , NULL , NULL , NULL } } ; mcxstatus ask_user ( const mcxTing* ask , const char* me ) { mcxIO* prompt = mcxIOnew("-", "r") ; mcxTing* ln = mcxTingEmpty(NULL, 10) ; mcxstatus status = STATUS_FAIL ; do { if (!isatty(fileno(stdin))) { yamErr(me, "unsafe mode; cannot prompt terminal!") ; break ; } if (mcxIOopen(prompt, RETURN_ON_FAIL)) break ; fputs(ask->str, stdout) ; fflush(stdout) /* mq fflush/fputs mix ? */ ; mcxIOreadLine(prompt, ln, MCX_READLINE_CHOMP) ; if (ln && ln->len == 1) { if (ln->str[0] == 'y' || ln->str[0] == 'Y') /* PARTY */ ; else if (ln->str[0] == 'n' || ln->str[0] == 'N') break ; else continue ; } else fprintf(stderr, "[%s]\n", ln->str) ; status = STATUS_OK ; } while (0) ; mcxTingFree(&ln) ; mcxIOfree(&prompt) ; return status ; } mcxstatus yamOpsDataAccess ( const mcxTing* access ) ; mcxbool yamOpList ( const char* mode ) { cmdHook* cmdhook = cmdHookDir ; mcxbool listAll = strstr(mode, "all") != NULL ; mcxbool match = listAll || 0 ; if (listAll || strstr(mode, "zoem")) { while (cmdhook && cmdhook->name) { if (cmdhook->descr) fprintf ( stdout , "%-11s %-20s %s\n" , cmdhook->name , !cmdhook->tag || !*(cmdhook->tag) ? "..." : cmdhook->tag , cmdhook->descr ) ; cmdhook++ ; } if (!strstr(mode, "legend")) fprintf(stdout, "Additionally supplying \"-l legend\" prints legend\n") ; match = 1 ; } if (listAll || strstr(mode, "legend")) { int m ; for (m=0;strLegend[m];m++) fprintf(stdout, "%s\n", strLegend[m]) ; match = 1 ; } if (listAll || strstr(mode, "builtin")) { fputs("\nBuilt-in aliases\n", stdout) ; cmdhook = cmdHookDir ; while (cmdhook && cmdhook->name) { if (cmdhook->composite) fprintf ( stdout , "%-15s maps to %s\n" , cmdhook->name , strlen(cmdhook->composite) ? cmdhook->composite : " (nothing)" ) ; cmdhook++ ; } match = 1 ; } return match ? TRUE : FALSE ; } yamSeg* expandNargs1 ( yamSeg* seg ) { return yamSegPush(seg, mcxTingInteger(NULL, yamCountScopes(arg1_g, 0))) ; } yamSeg* expandSHenv ( yamSeg* seg ) { const char* envp = getenv(arg1_g->str) ; return yamSegPush(seg, mcxTingNew(envp ? envp : "")) ; } yamSeg* expandLine ( yamSeg* seg ) { return yamSegPush(seg, mcxTingInteger(NULL, sourceGetLc())) ; } yamSeg* expandJumpLc1 ( yamSeg* seg ) { int ct = strtol(arg1_g->str, NULL, 10) ; sourceIncrLc(NULL, ct) ; return seg ; } yamSeg* expandThrow2 ( yamSeg* seg ) { int mode = !strcmp(arg1_g->str, "towel") ? SEGMENT_THROW : !strcmp(arg1_g->str, "done") ? SEGMENT_DONE : !strcmp(arg1_g->str, "error") ? SEGMENT_ERROR : 0 ; const char* type = mode == SEGMENT_THROW ? "exception" : mode == SEGMENT_DONE ? "bailout" : "error" ; mcxTing* msg = arg2_g->len ? arg(arg2_g) : NULL ; if (!mode) yamErr ( "throw#2" , "<%s> is unthrowable, throwing error instead" , arg1_g->str ) , mode = SEGMENT_ERROR ; if (msg) yamDigest(msg, msg, NULL) , yamErr(NULL, "[%s :: %s]", type, msg->str) , mcxTingFree(&msg) ; seg->flags |= mode ; return yamSegPushEmpty(seg) ; } yamSeg* expandTestFile2 ( yamSeg* seg ) { struct stat mystat ; return yamSegPush ( seg , mcxTingNew(stat(arg2_g->str, &mystat) ? "0" : "1") ) ; } yamSeg* expandTest3 ( yamSeg* seg ) { mcxTing* ops = arg(arg1_g) ; yamSeg* segops = yamStackPushTmp(ops) ; while (yamParseScopes(segops, 1, 0)) fprintf(stderr, "block: %s\n", arg1_g->str) ; yamStackFreeTmp(&segops) ; mcxTingFree(&ops) ; return yamSegPushEmpty(seg) ; } yamSeg* expandCatch2 ( yamSeg* seg ) { mcxbits accept = !strcmp(arg1_g->str, "done") ? SEGMENT_DONE : !strcmp(arg1_g->str, "towel") ? SEGMENT_DONE | SEGMENT_THROW : !strcmp(arg1_g->str, "error") ? SEGMENT_DONE | SEGMENT_THROW | SEGMENT_ERROR : 0 ; mcxTing* stuff ; if (!accept) { mcxErr("\\catch#2", "cannot catch <%s>", arg1_g->str) ; seg_check_ok(FALSE, seg) ; return yamSegPushEmpty(seg) ; } stuff = arg(arg2_g) ; yamDigest(stuff, stuff, seg) ; yamKeySet ( "__zoemstat__" , seg->flags & SEGMENT_ERROR ? "error" : seg->flags & SEGMENT_THROW ? "towel" : "done" ) ; BIT_OFF(seg->flags, accept) /* fixordoc: why is pushEmpty not needed? */ ; return yamSegPush(seg, stuff) ; } yamSeg* expandTry1 ( yamSeg* seg ) { mcxTing* stuff = arg(arg1_g) ; mcxbits flag_zoem = yamDigest(stuff, stuff, seg) ; mcxbool error = seg->flags & SEGMENT_ERROR ; mcxbool bailout = seg->flags & SEGMENT_DONE ; BIT_OFF(seg->flags, SEGMENT_INTERRUPT) ; yamKeySet("__zoemput__", stuff->str) ; yamKeySet ("__zoemstat__", !flag_zoem || bailout ? "done" : error ? "error" : "towel") ; mcxTingFree(&stuff) ; return seg ; } /* * fixme improve control * this one does not exit on failure */ yamSeg* expandZinsert1 ( yamSeg* seg ) { mcxTing* fname = arg(arg1_g) ; mcxTing* filetxt = mcxTingEmpty(NULL, 100) ; mcxIO* xf = NULL ; yamSeg* newseg = NULL ; if (yamDigest(fname, fname, seg)) { mcxTingFree(&filetxt) ; mcxTingFree(&fname) ; return yamSegPushEmpty(seg) ; } else if (!strcmp(fname->str, "stdia")) { sourceStdia(filetxt) ; newseg = seg ; } else { mcxTing* newtxt ; mcxTing* fnorig = mcxTingNew(fname->str) ; const mcxTing* infile = NULL ; if (!(xf = yamTryOpen(fname, &infile, 1)) && !infile) { mcxTell ( "zinsert#1" , "failure opening file <%s> (rerun?)" , fnorig->str ) ; newseg = seg ; } else if (infile) { newtxt = mcxTingPrint(NULL, "\\!{%s}", infile->str) ; newseg = yamSegPush(seg, newtxt) ; } else { if (mcxIOreadFile(xf, filetxt)) yamErr("zinsert#1", "error reading file <%s>", xf->fn->str) ; else newtxt = mcxTingPrint(NULL, "\\!{%s}", filetxt->str) , newseg = yamSegPush(seg, newtxt) ; } mcxTingFree(&fnorig) ; } mcxIOfree(&xf) ; mcxTingFree(&filetxt) ; mcxTingFree(&fname) ; return newseg ; } void text_map_vigenere ( mcxTing* data , mcxTing* key ) { char* p ; if (!key->len || mcxStrChrAint(key->str, islower, key->len)) { mcxErr("vigenere", "need lowercase key") ; return ; } for (p=data->str;pstr+data->len;p++) { unsigned char c = *p ; int shift = (unsigned char) key->str[(p-data->str)%key->len] - 'a' + 1 ; if (islower(c)) *p = "abcdefghijklmnopqrstuvwxyz"[(c-'a'+shift)%26] ; else if (isupper(c)) *p = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[(c-'A'+shift)%26] ; } } void text_map_vigenerex ( mcxTing* data , mcxTing* key ) { char* p ; if (!key->len) { mcxErr("vigenere", "need key") ; return ; } for (p=data->str;pstr+data->len;p++) { unsigned char c = *p ; int shift = (unsigned char) key->str[(p-data->str)%key->len] - 'a' + 1 ; if (shift < 0) shift *= -1 ; if (islower(c)) *p = "abcdefghijklmnopqrstuvwxyz_"[(c-'a'+shift)%27] ; else if (isupper(c)) *p = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"[(c-'A'+shift)%27] ; else if (c == ' ') *p = "abcdefghijklmnopqrstuvwxyz_"[(26+shift)%27] ; } } void text_map_caesar ( mcxTing* data , int shift ) { char* p ; for (p=data->str;pstr+data->len;p++) { unsigned char c = *p ; if (islower(c)) *p = "abcdefghijklmnopqrstuvwxyz"[(c-'a'+shift)%26] ; else if (isupper(c)) *p = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[(c-'A'+shift)%26] ; } } void text_map_alpha ( mcxTing* data , int base ) { int x, r, l, i, d = 0 ; x = atoi(data->str) ; if (x <0) mcxTingWrite(data, "-") , x = -x , d = 1 ; else mcxTingWrite(data, "") ; do { r = x % base ; x = x / base ; mcxTingNAppend(data, "_abcdefghijklmnopqrstuvwxyz"+r, 1) ; } while (x) ; l = data->len ; for (i=d;istr[i], g = data->str[l-i-1] ; data->str[i] = g ; data->str[l-i-1] = f ; } } void text_map_case ( mcxTing* data , mcxbool up ) { char* p ; for (p=data->str;pstr+data->len;p++) { unsigned char c = *p ; if (isalpha(c)) *p = up ? toupper(c) : tolower(c) ; } } yamSeg* expandTextmap2 ( yamSeg* seg ) { mcxTing* ops = arg(arg1_g) ; mcxTing* data = arg(arg2_g) ; yamSeg* segops = yamStackPushTmp(ops) ; const char* me = "\\textmap#2" ; mcxbits flag_zoem = 0 ; int x = 0 ; if ((flag_zoem = yamDigest(data, data, seg))) ; else while (2 == (x = yamParseScopes(segops, 2, 0))) { const char* key = arg1_g->str /* dangersign */ ; const char* val = arg2_g->str /* dangersign */ ; if (!strcmp(key, "word")) { if (!strcmp(val, "ucase")) text_map_case(data, TRUE) ; else if (!strcmp(val, "lcase")) text_map_case(data, FALSE) ; else yamErr(me, "unknown word mode <%s> (ignoring)", val) ; } else if (!strcmp(key, "number")) { if (!strcmp(val, "roman")) mcxTingRoman(data, atoi(data->str), FALSE) ; else if (!strcmp(val, "alpha") || !strcmp(val, "alpha27")) text_map_alpha(data, 27) ; else if (!strcmp(val, "alpha10")) text_map_alpha(data, 10) ; else if (!strcmp(val, "alpha2")) text_map_alpha(data, 2) ; else yamErr(me, "unknown number mode <%s> (ignoring)", val) ; } else if (!strcmp(key, "caesar")) { int num = atoi(val) % 26 ; text_map_caesar(data, num) ; } else if (!strcmp(key, "repeat")) { mcxTing* num = arg(arg2_g), *t ; int n ; if ((flag_zoem = yamDigest(num, num, seg))) break /* fixme memleak */ ; n = atoi(num->str) ; t = mcxTingKAppend(NULL, data->str, n < 0 ? 0 : n) ; mcxTingWrite(data, t->str) ; mcxTingFree(&t) ; mcxTingFree(&num) ; } else if (!strcmp(key, "vigenere")) text_map_vigenere(data, arg2_g) /* dangersign */ ; else if (!strcmp(key, "vigenerex")) text_map_vigenerex(data, arg2_g) /* dangersign */ ; else yamErr(me, "unknown mode <%s> (ignoring)", key) ; } if (x < 0 || x) /* error resp trailing arg */ yamErr(me, "syntax error (ignoring)") ; if (flag_zoem) mcxTingFree(&data) ; yamStackFreeTmp(&segops) ; mcxTingFree(&ops) ; return flag_zoem ? yamSegPushEmpty(seg) : yamSegPush(seg, data) ; } yamSeg* expandProtect1 ( yamSeg* seg ) { mcxTing* protected = yamProtect(arg1_g) ; return yamSegPush(seg, protected) ; } yamSeg* expandFinsert1 ( yamSeg* seg ) { mcxTing* fname = arg(arg1_g) ; mcxTing* filetxt = mcxTingEmpty(NULL, 100) ; mcxIO* xf = NULL ; mcxbits flag_zoem = yamDigest(fname, fname, seg) ; if (!flag_zoem && !(xf = yamTryOpen(fname, NULL, 1))) { flag_zoem = SEGMENT_ERROR ; mcxTell ( "finsert#1" , "failure opening file <%s> (rerun?)" , fname->str ) ; seg_check_flag(flag_zoem, seg) ; } if (!flag_zoem) yamReadData(xf, filetxt) ; else mcxTingEmpty(filetxt, 0) ; mcxIOfree(&xf) ; mcxTingFree(&fname) ; return yamSegPush(seg, filetxt) ; } yamSeg* expandDofile2 ( yamSeg* seg ) { mcxTing* fnsearch = arg(arg1_g) ; mcxTing* fname = NULL ; mcxTing* opts = arg2_g ; mcxbool ok = FALSE ; const char* me = "\\dofile#2" /* DON'T DIGEST OR OUTPUT AS LONG AS OPTS IS IN SCOPE */ ; int mode = 0 ; do { if (opts->len != 2) { yamErr(me, "Second arg <%s> not in {!?}x{+-}", opts->str) ; break ; } /* do output, use default sink */ if (!strncmp(opts->str, "!+", 2) || !strncmp(opts->str, "?+", 2)) mode = SOURCE_DEFAULT_SINK /* do not do output */ ; else if (!strncmp(opts->str, "!-", 2) || !strncmp(opts->str, "?-", 2)) /* OK */ ; else { yamErr(me, "Second arg <%s> not in {!?}x{+-}", opts->str) ; break ; } if (!sourceCanPush()) { yamErr ( me, "maximum file include depth (9) reached" "___ when presented with file <%s>" , fnsearch->str ) ; break ; } if (yamDigest(fnsearch, fnsearch, seg)) break ; fname = mcxTingNew(fnsearch->str) ; { mcxstatus status = sourceAscend(fnsearch, mode, chunk_size) ; if (status == STATUS_FAIL_OPEN) { if (strchr(opts->str, '?')) { ok = TRUE ; break ; } else { mcxErr(me, "failed to open file <%s>", fname->str) ; break ; } } else if (status != STATUS_OK) { mcxErr ( me , "error (%d) occurred while reading file <%s>" , (int) status , fname->str ) ; break ; } } ok = TRUE ; } while (0) ; seg_check_ok(ok, seg) ; mcxTingFree(&fnsearch) ; mcxTingFree(&fname) ; return ok ? seg : yamSegPushEmpty(seg) ; } yamSeg* expandXtag2 ( yamSeg* seg ) { mcxTing* tag = arg(arg1_g) ; mcxTing* ops = arg(arg2_g) ; return yamXtag(seg, tag, ops) ; } yamSeg* expandXtag1 ( yamSeg* seg ) { mcxTing* tag = arg(arg1_g) ; return yamXtag(seg, tag, NULL) ; } yamSeg* expandBang1 ( yamSeg* seg ) { mcxTing* stripped = mcxTingNew("\\") ; if (arg1_g->len > 1) mcxTingAppend(stripped, arg1_g->str) , mcxTingShrink(stripped, -1) ; return yamSegPushx(seg, stripped, SEGMENT_CONSTANT) ; } yamSeg* expandBang2 ( yamSeg* seg ) { if (arg1_g->len == 1) return yamSegPushx(seg, arg(arg2_g), seg->flags | SEGMENT_CONSTANT) ; else { mcxTing* txt = mcxTingPrint (NULL, "\\%.*s{%s}", (int) (arg1_g->len-1), arg1_g->str, arg2_g->str) ; return yamSegPushx(seg, txt, SEGMENT_CONSTANT) ; } return NULL /* unreachcode */ ; } yamSeg* expand_while_ ( yamSeg* seg , mcxbits opts ) { mcxbool dowhile = opts & 1 ; mcxbool whilst = opts & 2 ; mcxTing* condition = mcxTingNew(dowhile ? arg2_g->str : arg1_g->str) ; mcxTing* data = mcxTingNew(dowhile ? arg1_g->str : arg2_g->str) ; mcxTing* condition_ = mcxTingEmpty(NULL, 10) ; mcxTing* data_ = mcxTingEmpty(NULL, 10) ; mcxTing* newtxt = mcxTingEmpty(NULL, 10) ; mcxbits flag_zoem = STATUS_OK ; mcxbool guard = TRUE #if 0 ; sink* sk = sinkGetDefault() #endif ; if (!dowhile) { mcxTingWrite(condition_, condition->str) ; if ( (flag_zoem = yamDigest(condition_, condition_, seg)) || !atol(condition_->str) ) guard = FALSE ; } do { if (!guard) break ; mcxTingWrite(data_, data->str) ; if (whilst) flag_zoem = yamOutput(data_, NULL, ZOEM_FILTER_DEFAULT) ; else { flag_zoem = yamDigest(data_, data_, seg) ; mcxTingAppend(newtxt, data_->str) ; } /* fixme (doc?) a reason we append even ico failure? [yes] */ if (flag_zoem & SEGMENT_INTERRUPT) break ; mcxTingWrite(condition_, condition->str) ; if ((flag_zoem = yamDigest(condition_, condition_, seg))) break ; guard = atol(condition_->str) ? TRUE : FALSE ; } while (1) ; mcxTingFree(&data) ; mcxTingFree(&data_) ; mcxTingFree(&condition) ; mcxTingFree(&condition_) ; if (flag_zoem & SEGMENT_DONE) seg->flags =0 /* flag_zoem might be segless, from yamoutput */ ; else seg_check_flag(flag_zoem, seg) /* fixordoc: why is pushEmpty not needed? */ ; return yamSegPush(seg, newtxt) ; } yamSeg* expandDowhile2 ( yamSeg* seg ) { return expand_while_(seg, 1) ; } yamSeg* expandWhile2 ( yamSeg* seg ) { return expand_while_(seg, 0) ; } yamSeg* expandWhilst2 ( yamSeg* seg ) { return expand_while_(seg, 2) ; } yamSeg* expandApply2 ( yamSeg* seg ) { mcxTing *data = arg(arg2_g) ; mcxTing *newtxt = mcxTingEmpty(NULL, 10) ; char* p = arg1_g->str ; int delta = 0 ; const char* me = "\\apply#2" ; mcxTing *key = NULL ; yamSeg *tblseg = NULL ; int x, k, keylen, namelen ; mcxbool ok = FALSE ; mcxbits keybits = 0 ; while (isspace((unsigned char) *p)) p++ ; key = mcxTingNew(p) ; do { if (yamDigest(data, data, seg)) break ; if (yamDigest(key, key, seg)) break ; keylen = checkusrsig(key->str, key->len, &k, &namelen, &keybits) ; if (keylen < 0 || namelen < 0) { yamErr(me, "key part not ok") ; break ; } if (k<=0 || k > 9) { yamErr (me, "loop number <%d> not in [1,9] for key <%s>", k, key->str) ; break ; } if (!(keybits & KEY_CALLBACK)) { yamErr(me, "cannot operate on key <%s>", key->str) ; break ; } else if (keybits & KEY_ANON) { int cc ; if ((cc = yamClosingCurly(key, keylen, NULL, RETURN_ON_FAIL))<0) { yamErr ( me , "anonymous key <%s> not ok (%d/%d)" , key->str , cc+keylen+1 , key->len ) ; break ; } mcxTingNWrite(key_g, key->str, keylen) ; mcxTingNWrite(arg1_g, key->str+keylen+1, cc-1) ; delta = 1 ; } else if (keylen != key->len) /* mixed sign comparison */ { yamErr ( me , "key <%s> is not of the right \\foo, \\\"foo::foo\", and \\$foo" , key->str ) ; break ; } else if (keybits & KEY_PRIME) mcxTingWrite(key_g, key->str+1) ; else if (keybits & KEY_GLOBAL) mcxTingWrite(key_g, key->str+2) ; else mcxTingWrite(key_g, key->str) ; tblseg = yamStackPushTmp(data) /* perhaps this block should be encapsulated by parse.c * pity we have yamExpandKey here. * Also, yamStackPushTmp would like to set bit * that is checked by yamSegNew, but we cannot do that * because of the yamExpandKey below. * Seems we do full expansion here. */ ; while ((x = yamParseScopes(tblseg, k, delta)) == k) { yamSeg* newseg = yamExpandKey(tblseg, keybits) ; if (!newseg) { yamErr(me, "key <%s> does not expand", key->str) ; goto done /* fixme */ ; } else if (newseg != tblseg) /* primitives may return same segment */ { mcxTingAppend(newtxt, newseg->txt->str) ; yamSegFree(&newseg) ; } } if (!x) ; else if ( x < 0) { mcxErr(me, "parse error!") ; break ; } else if (x < k) mcxErr(me, "(ignoring) trailing arguments") ; ok = TRUE ; } while (0) ; done : seg_check_ok(ok, seg) ; mcxTingFree(&data) ; mcxTingFree(&key) ; yamStackFreeTmp(&tblseg) ; return yamSegPush(seg, newtxt) ; } yamSeg* expandTable5 ( yamSeg* seg ) { mcxTing *txtnum = arg(arg1_g) ; mcxTing *txtlft = arg(arg2_g) ; mcxTing *txtmdl = arg(arg3_g) ; mcxTing *txtrgt = arg(arg4_g) ; mcxTing *data = arg(arg5_g) ; mcxbool ok = FALSE ; yamSeg *tmpseg = NULL ; mcxTing *txtall = mcxTingEmpty(NULL, 100) ; int x, k ; do { if (yamDigest(data, data, seg) || yamDigest(txtnum, txtnum, seg)) break ; k = atoi(txtnum->str) ; if (k<=0) { yamErr("\\table#5", "nonpositive loop number <%d>", k) ; break ; } tmpseg = yamStackPushTmp(data) ; while ((x = yamParseScopes(tmpseg, k, 0)) == k) { int i ; mcxTingAppend(txtall, txtlft->str) ; for (i=1;istr) ; mcxTingAppend(txtall, txtmdl->str) ; } mcxTingAppend(txtall, (key_and_args_g+k)->str) ; mcxTingAppend(txtall, txtrgt->str) ; } if (x < 0) break ; ok = TRUE ; } while (0) ; seg_check_ok(ok, seg) ; mcxTingFree(&txtnum) ; mcxTingFree(&txtlft) ; mcxTingFree(&txtmdl) ; mcxTingFree(&txtrgt) ; yamStackFreeTmp(&tmpseg) ; mcxTingFree(&data) ; return yamSegPush(seg, txtall) ; } yamSeg* expandFormat2 ( yamSeg* seg ) { return yamFormat2(seg) ; } yamSeg* expandFormatted1 ( yamSeg* seg ) { return yamFormatted1(seg, arg1_g->str) ; } yamSeg* expandWrite3 ( yamSeg* seg ) { mcxTing* fname = arg(arg1_g) ; mcxTing* yamtxt = arg(arg3_g) ; mcxIO *xfout = NULL ; mcxbits flag_zoem = SEGMENT_ERROR ; int fltidx = 1 ; fflush(NULL) ; fltidx = !strcmp(arg2_g->str, "device") ? ZOEM_FILTER_DEVICE : !strcmp(arg2_g->str, "txt") ? ZOEM_FILTER_TXT : !strcmp(arg2_g->str, "copy") ? ZOEM_FILTER_COPY : -1 ; do { if (fltidx < 0) { yamErr("\\write#3", "unknown filter <%s>", arg2_g->str) ; break ; } if (yamDigest(fname, fname, seg)) break ; if (!(xfout = yamOutputNew(fname->str))) break ;if(0)fprintf(stderr, "set fnwrite %s\n", fname->str) ; if (strcmp(fname->str, "stderr")) yamKeyDef("__fnwrite__", fname->str) ; /* sinkPush(xfout->usr, fltidx) */ ; if ( (flag_zoem = yamOutput(yamtxt, xfout->usr, fltidx)) && !stressWrite ) break ; flag_zoem = 0 ; } while (0) ; if (xfout) { fflush(xfout->fp) ; /* sinkPop(xfout->usr) */ ; } if (strcmp(fname->str, "stderr")) yamKeyDeletex("__fnwrite__") ;if(0)fprintf(stderr, "unset fnwrite %s\n", fname->str) ; seg_check_flag(flag_zoem, seg) ; mcxTingFree(&fname) ; mcxTingFree(&yamtxt) ; return flag_zoem ? yamSegPushEmpty(seg) : seg ; } yamSeg* expandDollar2 ( yamSeg* seg ) { mcxTing* device = yamKeyGet(devtxt_g) ; if (!device) { yamErr ( "\\$" , "key [\\__device__] not defined, rendering use of <%s> useless" , key_g->str ) ; seg_check_ok(FALSE, seg) ; return yamSegPushEmpty(seg) ; } else if (!strcmp(device->str, arg1_g->str)) { mcxTing* txt = arg(arg2_g) ; return yamSegPush(seg, txt) ; } else return seg ; } yamSeg* expandUndef1 ( yamSeg* seg ) { int namelen = 0 ; mcxbits keybits = 0 ; int keylen = checkusrsig(arg1_g->str, arg1_g->len, NULL, &namelen, &keybits) ; const char* me = "\\undef#1" ; mcxTing* val = NULL ; do { const char* key = arg1_g->str /* dangersign, do not eval henceforth */ ; if (keylen <= 0 || keylen != arg1_g->len) /* mixed sign comparison */ { yamErr(me, "not a valid key signature: <%s>", arg1_g->str) ; break ; } if (keybits & KEY_GLOBAL) key += 2 ; if (!(val = yamKeyDelete(key, keybits & KEY_GLOBAL))) { yamErr(me, "key <%s> not defined in target scope", arg1_g->str) ; break ; } } while (0) ; if (!val) { seg_check_ok(FALSE, seg) ; return yamSegPushEmpty(seg) ; } mcxTingFree(&val) ; return seg ; } yamSeg* expandDefined2 ( yamSeg* seg ) { mcxTing *val ; mcxTing *type = arg(arg1_g) ; mcxTing *access= arg(arg2_g) ; char* yes = "1" ; char* no = "0" ; char* yn = "no" ; mcxbool ok = FALSE ; const char* me = "\\defined#2" ; mcxbits keybits = 0 ; int namelen = 0 ; do { if (yamDigest(access, access, seg)) { yamErr(me, "access string does not eval") ; break ; } if (!strcmp(type->str, "key") || !strcmp(type->str, "lkey")) { if ( checkusrsig(access->str, access->len, NULL, &namelen, &keybits) != access->len /* mixed sign comparison */ ) { yamErr (me, "argument <%s> is not a valid key signature", type->str) ; break ; } } if (!strcmp(type->str, "key")) { val = yamKeyGet(access) ; yn = val ? yes : no ; } else if (!strcmp(type->str, "lkey")) { val = yamKeyGetLocal(access) ; yn = val ? yes : no ; } else if (!strcmp(type->str, "data") || !strcmp(type->str, "%")) { if (yamOpsDataAccess(access)) break ; yn = yamDataGet() ? yes : no ; } else if ( !strcmp(type->str, "zoem") || !strcmp(type->str, "primitive") || !strcmp(type->str, "builtin") ) { const char* cps = NULL ; xpnfnc xpf = yamOpGet(access, &cps) ; yn = !strcmp(type->str, "zoem") && (cps || xpf) ? yes : !strcmp(type->str, "primitive") && xpf ? yes : !strcmp(type->str, "builtin") && cps ? yes : no ; } else if (!strcmp(type->str, "ENV")) { yn = getenv(access->str) ? yes : no ; } else { yamErr(me, "invalid type <%s>", type->str) ; break ; } ok = TRUE ; } while (0) ; seg_check_ok(ok, seg) ; mcxTingFree(&access) ; mcxTingFree(&type) ; return ok ? yamSegPush(seg, mcxTingNew(yn)) : yamSegPushEmpty(seg) ; } yamSeg* expandIf3 ( yamSeg* seg ) { mcxTing* bool = arg(arg1_g) ; mcxTing* case1 = arg(arg2_g) ; mcxTing* case0 = arg(arg3_g) ; int b ; if (yamDigest(bool, bool, seg)) { yamErr("\\if#3", "condition does not parse") ; mcxTingFree(&case0) ; mcxTingFree(&case1) ; mcxTingFree(&bool) ; return yamSegPushEmpty(seg) ; } b = bool->len ? atoi(bool->str) : 0 ; mcxTingFree(&bool) ; if (b) { mcxTingFree(&case0) ; return yamSegPush(seg, case1) ; } else { mcxTingFree(&case1) ; return yamSegPush(seg, case0) ; } return NULL /* unreachcode */ ; } /* * Does not change the contents of access, does not claim ownership. * *DOES* take ownership of argk_g. */ mcxstatus yamOpsDataAccess ( const mcxTing* access ) { if (access->len == 0) { n_args_g = 0 ; } else if (seescope(access->str, access->len) >= 0) { yamSeg* tmpseg = yamStackPushTmp((mcxTing*) access) /* dirty */ ; if (yamParseScopes(tmpseg, 9, 0) < 0) { yamStackFreeTmp(&tmpseg) ; return STATUS_FAIL ; } yamStackFreeTmp(&tmpseg) ; } else { n_args_g = 1 ; mcxTingWrite(arg1_g, access->str) ; } return STATUS_OK ; } yamSeg* expandGrapeDump ( yamSeg* seg ) { mcxTing* access = arg(arg1_g) ; mcxbool ok = TRUE ; do { if (yamDigest(access, access, seg)) break ; if (yamOpsDataAccess(access)) break ; if (yamDataPrint()) { yamErr("\\dump#1", "no value associated with <%s>", access->str) ; break ; } ok = TRUE ; } while (0) ; seg_check_ok(ok, seg) ; mcxTingFree(&access) ; return seg ; } yamSeg* expandGrapeFree ( yamSeg* seg ) { mcxTing* access = arg(arg1_g) ; mcxbool ok = TRUE /* NOTE this routine never fails, we start with ok = TRUE */ ; do { if (yamDigest(access, access, seg)) break ; if (yamOpsDataAccess(access)) break ; if (yamDataFree()) { yamErr("\\free#1", "no value associated with <%s>", access->str) ; break ; } ok = TRUE ; } while (0) ; seg_check_ok(ok, seg) ; mcxTingFree(&access) ; return seg ; } /* Never fails, only warns */ yamSeg* expandGrapeGet ( yamSeg* seg ) { const char* str = NULL ; mcxTing* access = arg(arg1_g) ; mcxbool ok = TRUE /* on purpose; grape key absence -> "" */ ; do { if (yamDigest(access, access, seg)) break ; if (yamOpsDataAccess(access)) break ; if (!(str = yamDataGet())) { yamErr("\\%#1", "no value associated with <%s>", access->str) ; break ; } ok = TRUE ; } while(0) ; seg_check_ok(ok, seg) ; mcxTingFree(&access) ; return yamSegPush(seg, mcxTingNew(str ? str : "")) ; } mcxstatus veto_system ( char* args[] , int l , const char* me ) { mcxTing* ask = mcxTingEmpty(NULL, 80) ; mcxstatus status = STATUS_FAIL ; int i = 0 ; do { mcxTingWrite ( ask , "\n? do you want this command to be exercised? (y/n)\n? [" ) ; for (i=0; istr) ; mcxTing* arx = arg(arg2_g) ; mcxTing* data = arg(arg3_g) ; mcxTing* out = NULL ; yamSeg* argseg= NULL ; char* args[YAM_ARG_MAX+1] ; int k, i ; mcxbool ok = FALSE ; const char* me = "\\system#3" ; mcxbool listed= system_allow && strstr(system_allow->str, cmd_->str) ? TRUE : FALSE ; mcxTingFree(&cmd_) ; do { if (!listed && systemAccess == SYSTEM_SAFE) { yamErr ( me , "system calls are not allowed (use --unsafe or --unsafe-silent)" ) ; break ; } if (yamDigest(arx, arx, seg)) break ; if (yamDigest(data, data, seg)) break ; argseg = yamStackPushTmp(arx) ; args[0] = cmd->str ; if ((k = yamParseScopes(argseg, YAM_ARG_MAX, 0)) < 0) { yamErr(me, "second argument not a vararg") ; break ; } for (i=0; iflags & SEGMENT_INTERRUPT)) mcxErr(me, "continuing (cf --system-honor)") ; else if (!ok) seg_check_ok(ok, seg) ; return yamSegPush(seg, out) /* fixme: systemHonor logic still ok ? */ ; } /* pivot ? switch : branch */ yamSeg* expand_switch_ ( yamSeg* seg , mcxTing* pivot /* we claim ownership */ , mcxTing* body /* we claim ownership */ ) { mcxTing* clause = mcxTingEmpty(NULL, 30) ; mcxTing* yamtxt = mcxTingEmpty(NULL, 30) ; mcxbool ok = TRUE ; int x = -1 ; yamSeg* tmpseg = yamStackPushTmp(body) ; if ( (tmpseg->flags & SEGMENT_ERROR) || (pivot && yamDigest(pivot, pivot, seg)) ) ok = FALSE ; while (ok && (x = yamParseScopes(tmpseg, 2, 0)) == 2) { mcxTingWrite(clause, arg1_g->str) ; mcxTingWrite(yamtxt, arg2_g->str) ; if (yamDigest(clause, clause, seg)) { ok = FALSE ; break ; } if (pivot) { int n_scopes = yamCountScopes(clause, 0) ; if (n_scopes >= 1) { yamSeg* tmp2seg = yamStackPushTmp(clause) ; int y = yamParseScopes(tmp2seg, 9, 0), yi ; for (yi=1;yi<=y;yi++) if (!strcmp(pivot->str, key_and_args_g[yi].str)) break ; if (yi != y+1) break ; } else if (!strcmp(clause->str, pivot->str)) break ; } else /* branch: empty string fails */ { if (clause->len && atol(clause->str)) break ; } } if (!ok) /* clause parse error or stack size */ /* NOTHING */ ; else if (x < 0) /* parse error (e.g. no closing scope) */ ok = FALSE ; else if (x == 1) /* fall through / else clause */ mcxTingWrite(yamtxt, arg1_g->str) ; else if (x == 0) /* nothing matched */ mcxTingEmpty(yamtxt, 0) ; if (!ok) mcxTingEmpty(yamtxt, 0) ; seg_check_ok(ok, seg) ; mcxTingFree(&pivot) ; mcxTingFree(&clause) ; yamStackFreeTmp(&tmpseg) ; mcxTingFree(&body) ; return yamSegPush(seg, yamtxt) ; } yamSeg* expandSwitch2 ( yamSeg* seg ) { mcxTing* pivot = arg(arg1_g) ; mcxTing* body = arg(arg2_g) ; return expand_switch_(seg, pivot, body) ; } yamSeg* expandBranch1 ( yamSeg* seg ) { mcxTing* body = arg(arg1_g) ; return expand_switch_(seg, NULL, body) ; } yamSeg* expandConstant1 ( yamSeg* seg ) { mcxTing* yamtxt = arg(arg1_g) ; yamSeg* newseg = yamStackPushTmp(yamtxt) ; mcxbool ok = TRUE ; int x = -1 ; while ((x = yamParseScopes(newseg, 2, 0)) == 2) { mcxTing* key = arg(arg1_g) ; if (yamConstantNew(key, arg2_g->str) != key) mcxTingFree(&key) ; } if (x < 0) ok = FALSE ; else if (x == 1) yamErr("\\constant#1", "spurious element") ; yamStackFreeTmp(&newseg) ; mcxTingFree(&yamtxt) ; seg_check_ok(ok, seg) ; return seg ; } yamSeg* expandSpecial1 ( yamSeg* seg ) { mcxTing* yamtxt = arg(arg1_g) ; int x = -1 ; int ct = 0 ; mcxbool ok = TRUE ; yamSeg* newseg ; if (yamDigest(yamtxt, yamtxt, seg)) return yamSegPush(seg, mcxTingEmpty(yamtxt, 0)) ; newseg = yamStackPushTmp(yamtxt) ; while ((x = yamParseScopes(newseg,2, 0)) == 2) { int c = atoi(arg1_g->str) ; yamSpecialSet(c, arg2_g->str) ; ct += x ; } if (x < 0) ok = FALSE ; else if (!ct) yamSpecialClean() /* perhaps we should reset the special level of the default output * stream to 1. */ ; else if (x == 1) yamErr("\\special#1", "spurious element") ; yamStackFreeTmp(&newseg) ; mcxTingFree(&yamtxt) ; seg_check_ok(ok, seg) ; return seg ; } yamSeg* expandRegister2 ( yamSeg* seg ) { if (!strcmp(arg1_g->str, "END")) { mcxTing* regee = arg(arg2_g) ; mcxLink* lk = reg_end_g ; while (lk->next) lk = lk->next ; mcxLinkAfter(lk, regee) ; } else yamErr("\\register#2", "unsupported tag <%s>", arg1_g->str) ; return seg ; } mcxstatus mod_registrees ( void ) { mcxLink* regee = reg_end_g->next ; while (regee) { mcxTing* stuff = regee->val ; if (yamOutput(stuff, NULL, ZOEM_FILTER_DEFAULT)) break ; regee = regee->next ; } return regee ? STATUS_FAIL : STATUS_OK ; } yamSeg* expand_cmp_ ( yamSeg* seg , int mode ) { mcxTing* test = arg(arg1_g) ; mcxTing* op1 = arg(arg2_g) ; mcxTing* op2 = arg(arg3_g) ; char* ret = "0" ; mcxbool ok = FALSE ; const char* me = mode == 's' ? "cmp#3" : "eqt#3" ; double diff, abs ; do { if (!strstr("cp\001lt\001lq\001eq\001gq\001gt\001ne", test->str)) { mcxErr(me, "unknown mode <%s>", test->str) ; break ; } if (yamDigest(op1, op1, seg) || yamDigest(op2, op2, seg)) break ; diff = (mode == 's') ? strcmp(op1->str, op2->str) : atof(op1->str) - atof(op2->str) ; abs = diff*MCX_SIGN(diff) ; if (!strcmp(test->str, "cp")) ret = abs < precision_g ? "0" : diff > 0 ? "1" : "-1" ; else if ( (!strcmp(test->str, "lt") && diff < -precision_g) || (!strcmp(test->str, "lq") && diff < precision_g) || (!strcmp(test->str, "eq") && abs <= precision_g) || (!strcmp(test->str, "gq") && diff > -precision_g) || (!strcmp(test->str, "gt") && diff > precision_g) || (!strcmp(test->str, "ne") && abs > precision_g) ) ret = "1" ; ok = TRUE ; } while (0) ; mcxTingFree(&op1) ; mcxTingFree(&op2) ; mcxTingFree(&test) ; seg_check_ok(ok, seg) ; return ok ? yamSegPush(seg, mcxTingNew(ret)) : yamSegPushEmpty(seg) ; } yamSeg* expandEqt3 ( yamSeg* seg ) { return expand_cmp_(seg, 'i') ; } yamSeg* expandCmp3 ( yamSeg* seg ) { return expand_cmp_(seg, 's') ; } yamSeg* expandInspect4 ( yamSeg* seg ) { return yamInspect4(seg) ; } yamSeg* expandTr2 ( yamSeg* seg ) { mcxTing* specs = arg(arg1_g) ; mcxTing* data = arg(arg2_g) ; mcxTing* src = NULL ; mcxTing* dst = NULL ; mcxTing* del = NULL ; mcxTing* sqs = NULL ; mcxbool ok = FALSE ; yamSeg* newseg = yamStackPushTmp(specs) ; int x = -1 ; while ((x = yamParseScopes(newseg, 2, 0)) == 2) { const char* key = arg1_g->str ; if (!strcmp(key, "from")) src = arg(arg2_g), ting_tilde_expand(src, YAM_TILDE_UNIX) ; else if (!strcmp(key, "to")) dst = arg(arg2_g), ting_tilde_expand(dst, YAM_TILDE_UNIX) ; else if (!strcmp(key, "delete")) del = arg(arg2_g), ting_tilde_expand(del, YAM_TILDE_UNIX) ; else if (!strcmp(key, "squash")) sqs = arg(arg2_g), ting_tilde_expand(sqs, YAM_TILDE_UNIX) ; else if (!strcmp(key, "debug")) mcx_tr_debug = strchr(arg2_g->str, '1') ? TRUE : FALSE ; else { mcxErr("tr#2", "strange key <%s>", key) ; break ; } } yamStackFreeTmp(&newseg) ; mcxTingFree(&specs) ; do { int newlen ; if (x != 0) break ; if (yamDigest(data, data, seg)) break ; yamUnprotect(data) ; newlen = mcxTingTr ( data , src ? src->str : NULL , dst ? dst->str : NULL , del ? del->str : NULL , sqs ? sqs->str : NULL , 0 ) ; if (newlen < 0) { yamErr("\\tr#2", "spec did not parse") ; break ; } { mcxTing* newdata = yamProtect(data) ; mcxTingFree(&data) ; data = newdata ; } ok = TRUE ; } while (0) ; seg_check_ok(ok, seg) ; mcxTingFree(&src) ; mcxTingFree(&dst) ; mcxTingFree(&del) ; mcxTingFree(&sqs) ; return yamSegPush(seg, data) ; } /* strcmp should be factored out */ enum { F_UNKNOWN = 1 , F_MUL , F_ADD , F_SUB , F_POW , F_FRAC , F_DIV , F_MOD , F_AND , F_OR , F_NOT , F_INV , F_MAX , F_MIN , F_CEIL, F_FLOOR, F_IRAND, F_DRAND , F_ABS , F_SIGN, F_ROUND , F_DEC, F_INC } ; int fType ( mcxTing* mode ) { const char* s = mode->str ; if (mode->len == 1) switch(*s) { case '+' : return F_ADD ; break ; case '-' : return F_SUB ; break ; case '/' : return F_FRAC ; break ; case '*' : return F_MUL ; break ; case '%' : return F_MOD ; break ; } else if (mode->len == 3) /* very poor addressing scheme, I know */ { if (!strcmp(s, "abs")) return F_ABS ; else if (!strcmp(s, "and")) return F_AND ; else if (!strcmp(s, "min")) return F_MIN ; else if (!strcmp(s, "max")) return F_MAX ; else if (!strcmp(s, "div")) return F_DIV ; else if (!strcmp(s, "mod")) return F_MOD ; else if (!strcmp(s, "pow")) return F_POW ; else if (!strcmp(s, "mul")) return F_MUL ; else if (!strcmp(s, "sub")) return F_SUB ; else if (!strcmp(s, "add")) return F_ADD ; else if (!strcmp(s, "sum")) return F_ADD ; else if (!strcmp(s, "dec")) return F_DEC ; else if (!strcmp(s, "inc")) return F_INC ; } else if (mode->len == 4) { if (!strcmp(s, "sign")) return F_SIGN ; else if (!strcmp(s, "ceil")) return F_CEIL ; } else { if (!strcmp(s, "round")) return F_ROUND ; else if (!strcmp(s, "floor")) return F_FLOOR ; else if (!strcmp(s, "irand")) return F_IRAND ; else if (!strcmp(s, "drand")) return F_DRAND ; else if (!strcmp(s, "or")) return F_OR ; else if (!strcmp(s, "**")) return F_POW ; else if (!strcmp(s, "//")) return F_DIV ; else if (!strcmp(s, "&&")) return F_AND ; else if (!strcmp(s, "||")) return F_OR ; } return F_UNKNOWN ; } yamSeg* expandF2 ( yamSeg* seg ) { mcxTing* mode = arg(arg1_g) ; mcxTing* ftxt = arg(arg2_g) ; mcxTing* yamtxt = NULL ; double f, g = 0.0 ; long i, j = 0 ; int modus = fType(mode) ; mcxbool ok = TRUE ; mcxbool integral = FALSE ;if(0)yamErr("f#2", "mode %s", mode) ; if (yamDigest(ftxt, ftxt, seg)) goto fail ; f = atof(ftxt->str) ; i = atoi(ftxt->str) ; switch(modus) { case F_FLOOR : g = floor(f) ; break ; case F_CEIL : g = ceil(f) ; break ; case F_ROUND : g = floor(f+0.5) ; break ; case F_ABS : g = f < 0 ? -f : f ; break ; case F_DRAND : g = (((unsigned long) random()) * 1.0 / (1.0 * RAND_MAX)) * f ; break ; case F_IRAND : j = ((unsigned long) random()) % (unsigned) i, integral = TRUE ; break ; case F_SIGN : j = f * MCX_SIGN(f) <= precision_g ? 0 : f<0 ? -1.0 : 1, integral = TRUE ; break ; case F_INC : g = f + 1.0 ; break ; case F_DEC : g = f - 1.0 ; break ; case F_NOT : g = f ? 0.0 : 1.0 ; break ; default : yamErr("\\f#2", "unknown mode <%s>", mode->str) ; goto fail ; } if (integral) yamtxt = mcxTingInteger(NULL, j) ; else { double eps = g - floor(g+0.5) ; if (eps * MCX_SIGN(eps) <= precision_g && g*MCX_SIGN(g) <= LONG_MAX) /* fixme */ yamtxt = mcxTingInteger(NULL, roundnear(g)) ; else yamtxt = mcxTingDouble(NULL, g, 10) ; } if (0) fail: ok = FALSE /* fixme ugly goto, even harmful */ ; if (!ok) yamtxt = mcxTingEmpty(yamtxt, 0) ; seg_check_ok(ok, seg) ; mcxTingFree(&ftxt) ; mcxTingFree(&mode) ; return yamSegPush(seg, yamtxt) ; } yamSeg* expandF3 ( yamSeg* seg ) { mcxTing* mode = arg(arg1_g) ; mcxTing* f1txt = arg(arg2_g) ; mcxTing* f2txt = arg(arg3_g) ; mcxTing* f3txt = NULL ; double eps, f1 = 0.0, f2 = 0.0, f3 = 0.0 ; long i1 = 0, i2 = 0, done = 0 ; int modus = fType(mode) ; mcxbool ok = TRUE ;if(0)yamErr("f#3", "mode %s", mode) ; if (yamDigest(f1txt, f1txt, seg)) goto fail ; f1 = atof(f1txt->str) ; i1 = atoi(f1txt->str) ; if ((modus == F_AND && !i1) || (modus == F_OR && i1)) { f3 = i1 ? 1.0 : 0.0 ; done = 1 /* short-circuit */ ; } else { if (yamDigest(f2txt, f2txt, seg)) goto fail ; f2 = atof(f2txt->str) ; i2 = atoi(f2txt->str) ; } ; if (done) /* nothing */ ; else switch(modus) { case F_ADD : f3 = f1 + f2 ; break ; case F_SUB : f3 = f1 - f2 ; break ; case F_FRAC : f3 = f2 ? (f1/f2) : 0 ; break ; case F_DIV : f3 = f2 ? floor (f1/f2) : 0 ; break ; case F_MUL : f3 = f1 * f2 ; break ; case F_POW : f3 = pow(fabs(f1), f2) ; break ; case F_AND : f3 = i1 && i2 ; break ; case F_OR : f3 = i1 || i2 ; break ; case F_MOD : f3 = f2 ? ((f1/f2)-floor(f1/f2))*f2 : 0 ; break ; case F_MAX : f3 = MCX_MAX(f1, f2) ; break ; case F_MIN : f3 = MCX_MIN(f1, f2) ; break ; case F_CEIL : f3 = (ceil(f1/f2))*f2 ; break ; case F_FLOOR : f3 = (floor(f1/f2))*f2 ; break ; default : yamErr("\\f#3", "unknown mode <%s>", mode->str) ; goto fail ; } if ( (modus == F_DIV || modus == F_FRAC || modus == F_MOD) && !f2 ) yamErr("\\f#3", "arithmetic exception for operator <%s>", mode->str) ; eps = f3 - floor(f3+0.5) ; if (eps * MCX_SIGN(eps) <= precision_g && f3*MCX_SIGN(f3) <= LONG_MAX) f3txt = mcxTingInteger(NULL, roundnear(f3)) ; else f3txt = mcxTingDouble(NULL, f3, 10) ; if(0) fail: ok = FALSE /* fixme ugly goto, even harmful */ ; if (!ok) f3txt = mcxTingEmpty(f3txt, 0) ; seg_check_ok(ok, seg) ; mcxTingFree(&f1txt) ; mcxTingFree(&f2txt) ; mcxTingFree(&mode) ; return yamSegPush(seg, f3txt) ; } yamSeg* expandFv2 ( yamSeg* seg ) { mcxTing* mode = arg(arg1_g) ; mcxTing* data = arg(arg2_g) ; long ival = 0 ; double fval = 0.0 ; yamSeg* valseg = NULL ; mcxTing* valtxt = NULL ; int x = -1 ; int modus = fType(mode) ; int ct = 0 ; mcxbool ok = TRUE ;if(0)yamErr("fv#2", "mode %s", mode) ; if (modus == F_MIN) fval = DBL_MAX ; else if (modus == F_MAX) fval = -DBL_MAX ; else if (modus == F_MUL) fval = 1.0 ; else if (modus == F_AND) ival = 1 ; else if (modus == F_OR) ival = 0 ; valseg = yamStackPushTmp(data) ; while (ok && (x = yamParseScopes(valseg, 1, 0)) == 1) { long i ; double f ; mcxTing* op = arg(arg1_g) ; if (yamDigest(op, op, seg)) { mcxTingFree(&op) ; goto fail /* fixme ugly goto */ ; } i = atoi(op->str) ; f = atof(op->str) ; mcxTingFree(&op) ; switch(modus) { case F_ADD : fval += f ; break ; case F_MUL : fval *= f ; break ; case F_AND : ival = ival && i ; break ; case F_OR : ival = ival || i ; break ; case F_MAX : fval = MCX_MAX(fval, f) ; break ; case F_MIN : fval = MCX_MIN(fval, f) ; break ; default : yamErr("\\fv#2", "unknown mode <%s>", mode->str) ; goto fail ; } ct++ ; if ((modus == F_OR && ival) || (modus == F_AND && !ival)) break /* short-circuit */ ; } if (x < 0) { goto fail ; } else if (ct == 0) { fval = 0.0 ; ival = 0 ; yamErr("\\fv#2", "I have an empty vararg!") ; } if (!fval) valtxt = mcxTingInteger(NULL, ival) ; else { double eps = fval - floor(fval+0.5) ; if (eps * MCX_SIGN(eps) <= precision_g && fval*MCX_SIGN(fval) <= LONG_MAX) valtxt = mcxTingInteger(NULL, roundnear(fval)) ; else valtxt = mcxTingDouble(NULL, fval, 10) ; } if(0) fail: ok = FALSE ; if (!ok) valtxt = mcxTingEmpty(valtxt, 0) ; seg_check_ok(ok, seg) ; yamStackFreeTmp(&valseg) ; mcxTingFree(&data) ; mcxTingFree(&mode) ; return yamSegPush(seg, valtxt) ; } mcxstatus veto_redirect ( const char* name , const char* me ) { mcxTing* ask = mcxTingEmpty(NULL, 80) ; mcxstatus status = STATUS_FAIL ; do { mcxTingPrint ( ask , "\n? do you allow writing to the file <%s> (y/n)\n? " , name ) ; if (ask_user(ask, me)) break ; status = STATUS_OK ; } while (0) ; mcxTingFree(&ask) ; return status ; } yamSeg* expandWriteto1 ( yamSeg* seg ) { mcxTing* newname = arg(arg1_g) ; const char* curname = sinkGetDefaultName() ; const char* me = "\\writeto#3" ; mcxIO* xf ; mcxbool ok = FALSE ; do { if (yamDigest(newname, newname, seg)) break ; if (strchr(newname->str, '/')) { if (systemAccess == SYSTEM_SAFE) { yamErr ( me , "filename contains path separator (cf --unsafe(-silent))" ) ; break ; } else if ( systemAccess == SYSTEM_UNSAFE && veto_redirect(newname->str, me) ) break ; } /* fixme, or not? pbb PBD */ if (!curname) yamErrx(1, "\\redirect#1 PANIC", "no current file") ; yamOutputClose(curname) ; if (!(xf = yamOutputNew(newname->str))) yamErrx(1, "\\redirect#1", "unable to open file <%s>", newname->str) /* fixme (no exit) */ ; mcxTell ( "zoem" , "changing current sink from <%s> to <%s>" , curname , newname->str ) ; sinkPush(xf->usr, -1) ; ok = TRUE ; } while (0) ; seg_check_ok(ok, seg) ; mcxTingFree(&newname) ; return ok ? seg : yamSegPushEmpty(seg) ; } yamSeg* expandPush1 ( yamSeg* seg ) { return usrDictPush(arg1_g->str) ? NULL : seg ; } yamSeg* expandPop1 ( yamSeg* seg ) { return usrDictPop(arg1_g->str) ? NULL : seg ; } yamSeg* expandEval1 ( yamSeg* seg ) { mcxTing* txt = arg(arg1_g) ; yamDigest(txt, txt, seg) ; BIT_OFF(seg->flags, SEGMENT_DONE) /* fixordoc: why not push empty in case of error? */ ; return yamSegPush(seg, txt) ; } yamSeg* expandExit0 ( yamSeg* seg_unused cpl__unused ) { yamErrx(1,"\\exit", "premature exit -- goodbye") ; return NULL ; } yamSeg* expandTrace1 ( yamSeg* seg ) { mcxTing* t = arg(arg1_g) ; static int tracing_prev = 0 ; int val ; if (yamDigest(t, t, seg)) { mcxTingFree(&t) ; return seg ; } val = atoi(t->str) ; if (val == -3) tracing_prev = yamTracingSet(tracing_prev) ; else if (val == -4) showTracebits() ; else tracing_prev = yamTracingSet(val) ; mcxTingFree(&t) ; return val == -4 ? seg : yamSegPush(seg, mcxTingInteger(NULL, tracing_prev)) ; } yamSeg* expandEnv4 ( yamSeg* seg ) { return yamEnvNew(arg1_g->str, arg2_g->str, arg3_g->str, arg4_g->str, seg) ? NULL : seg ; } yamSeg* expandBegin2 ( yamSeg* seg ) { const char* b = yamEnvOpen(arg1_g->str, arg2_g->str, seg) ; mcxTing* val = b ? mcxTingNew(b) : NULL ; if (!val) { seg_check_ok(FALSE, seg) ; return yamSegPushEmpty(seg) ; } return yamSegPush(seg, val) ; } /* fixme; make clearer exit(1) logic, e.g. use yamSegPushEmpty. */ yamSeg* expandEnd1 ( yamSeg* seg ) { mcxTing* end = arg(arg1_g) ; const char* def = yamEnvEnd(end->str, seg) ; mcxTing* val = def ? mcxTingNew(def) : NULL ; mcxbool ok = FALSE ; do { if (!val) { yamErr("\\end#2", "env <%s> not found", end->str) ; val = mcxTingEmpty(NULL, 0) ; break ; } if (yamDigest(val, val, seg)) break /* must eval now, because we need to pop here */ ; if (yamEnvClose(end->str)) /* this pops the env stack */ break ; ok = TRUE ; } while (0) ; seg_check_ok(ok, seg) ; mcxTingFree(&end) ; return yamSegPush(seg, val) ; } yamSeg* expandGet2 ( yamSeg* seg ) { mcxTing* val = yamKeyGetByDictName(arg1_g, arg2_g) ; if (!val) { yamErr("\\get#2", "dict/key <%s/%s> not found", arg1_g->str, arg2_g->str) ; seg_check_ok(FALSE, seg) ; return yamSegPushEmpty(seg) ; } return yamSegPush(seg, arg(val)) ; } yamSeg* expand_set_ ( yamSeg* seg , const char* me , mcxbits callbits , const mcxTing* dict_name ) { mcxbool data = arg1_g->str[0] == '%' ; mcxTing* valtxt = arg(arg2_g) ; mcxbool ok = FALSE ; mcxTing* key = NULL ; mcxTing* access = NULL ; int keylen ; if (data) do { mcxbool overwrite = FALSE ; access = mcxTingNew(arg1_g->str+1) ; if (callbits & YAM_SET_EXPAND && yamDigest(valtxt, valtxt, seg)) break ; if (yamDigest(access, access, seg)) break ; if (yamOpsDataAccess(access)) break ; if (yamDataSet(valtxt->str, callbits, &overwrite, callbits & YAM_SET_COND)) break ; if (callbits & YAM_SET_WARN && overwrite) yamErr (me, "overwrite in access/data <%s><%s>", access->str, valtxt->str) ; ok = TRUE ; } while (0) ; else do { int namelen = 0 ; mcxbits keybits = 0 ; const mcxTing* inserted = NULL ; key = arg(arg1_g) ; keylen = checkusrsig(key->str, key->len, NULL, &namelen, &keybits) ; if (keylen <= 0 || keylen != key->len) /* mixed sign comparison */ { yamErr(me, "not a valid key signature: <%s>", key->str) ; break ; } else if (keybits & KEY_ZOEMONLY) { yamErr(me, "attempt to use reserved syntax: <%s>", key->str) ; break ; } else if (mcxHashSearch(key, yamTable_g, MCX_DATUM_FIND)) { mcxErr(me, "zoem primitive <%s> is overwritten (not recommended)", key->str) ; mcxErr(me, "primitive is still available as <'%s>", key->str) ; } if (keybits & KEY_GLOBAL) callbits |= YAM_SET_GLOBAL /* fixme-uglyish */ , mcxTingDelete(key, 0, 2) /* get rid of leading '' */ ; if (callbits & YAM_SET_EXPAND && yamDigest(valtxt, valtxt, seg)) { yamErr(me, "argument did not parse") ; break ; } inserted = yamKeyInsert ( key , valtxt->str , valtxt->len , callbits & (YAM_SET_COND | YAM_SET_APPEND | YAM_SET_GLOBAL | YAM_SET_EXISTING) , dict_name ) ; if (inserted && inserted != key) { if (callbits & YAM_SET_WARN) yamErr(me, "overwriting key <%s>",key->str) ; mcxTingFree(&key) ; } /* !inserted may occur when resetting key (YAM_SET_EXISTING) * but key was not found. */ ok = TRUE ; } while (0) ; if (!ok) mcxTingFree(&key) /* fixme better key-init-free logic */ ; seg_check_ok(ok, seg) ; mcxTingFree(&access) ; mcxTingFree(&valtxt) ; return ok ? seg : yamSegPushEmpty(seg) ; } yamSeg* expandDef2 ( yamSeg* seg ) { return expand_set_(seg, "\\def#2", YAM_SET_WARN, NULL) ; } yamSeg* expandDefx2 ( yamSeg* seg ) { return expand_set_(seg, "\\defx#2", YAM_SET_EXPAND | YAM_SET_WARN, NULL) ; } static void my_splice ( mcxTing* dest , mcxTing* val , mcxTing* oldval , int start , int width ) { if (oldval) { mcxTingNWrite(dest, oldval->str, oldval->len) ; mcxTingSplice(dest, val->str, start, width, val->len) ; } else mcxTingNWrite(dest, val->str, val->len) ; } yamSeg* expandSet3 ( yamSeg* seg ) { mcxTing* spec = arg(arg1_g) ; mcxTing* key = arg(arg2_g) ; mcxTing* val = arg(arg3_g) ; mcxTing* condition = NULL ; mcxTing* dict_name = NULL ; mcxbool unless = FALSE ; yamSeg* tmpseg = yamStackPushTmp(spec) ; mcxbits bits = 0 ; mcxbool vararg = FALSE ; mcxTing* thestart = NULL, *thewidth = NULL ; int y ; while (2 == (y = yamParseScopes(tmpseg, 2, 0))) { if (!strcmp(arg1_g->str, "modes")) { if (strchr(arg2_g->str, 'u')) bits |= YAM_SET_UNARY ; if (strchr(arg2_g->str, 'x')) bits |= YAM_SET_EXPAND ; if (strchr(arg2_g->str, 'c')) bits |= YAM_SET_COND ; if (strchr(arg2_g->str, 'e')) bits |= YAM_SET_EXISTING ; if (strchr(arg2_g->str, 'w')) bits |= YAM_SET_WARN ; if (strchr(arg2_g->str, 't')) bits |= YAM_SET_TREE ; if (strchr(arg2_g->str, 'g')) bits |= YAM_SET_GLOBAL ; if (strchr(arg2_g->str, 'l')) bits |= YAM_SET_LOCAL ; if (strchr(arg2_g->str, 'a')) bits |= YAM_SET_APPEND ; if (strchr(arg2_g->str, 'v')) vararg = TRUE ; } else if (!strcmp(arg1_g->str, "start")) thestart = mcxTingNew(arg2_g->str) ; else if (!strcmp(arg1_g->str, "width")) thewidth = mcxTingNew(arg2_g->str) ; else if (!strcmp(arg1_g->str, "if")) condition = mcxTingNew(arg2_g->str) ; else if (!strcmp(arg1_g->str, "unless")) condition = mcxTingNew(arg2_g->str) , unless = TRUE ; else if (!strcmp(arg1_g->str, "dict")) dict_name = mcxTingNew(arg2_g->str) ; else yamErr("\\set#3", "ignoring spec <%s>", arg1_g->str) ; } yamStackFreeTmp(&tmpseg) ; mcxTingFree(&spec) ; do { if (condition) { mcxbits flag_zoem = yamDigest(condition, condition, seg) ; mcxbool condition_ok = atoi(condition->str) ; if (flag_zoem) break ; else if ( ( unless && condition_ok) || (!unless && !condition_ok) ) break ; } if (vararg) { yamSeg* tmpseg = yamStackPushTmp(val) ; while (!seg->flags && 2 == (y = yamParseScopes(tmpseg, 2, 0))) seg = expand_set_(seg, "\\set#3", bits, dict_name) ; yamStackFreeTmp(&tmpseg) ; } else { if (thestart || thewidth) { mcxTing* oldboy = yamKeyGet(key) ; mcxbits flag_zoem = thestart ? yamDigest(thestart, thestart, seg) : 0 ; flag_zoem |= thewidth ? yamDigest(thewidth, thewidth, seg) : 0 ; if (flag_zoem) break ; my_splice ( arg2_g , val , oldboy , thestart ? atoi(thestart->str) : 0 , thewidth ? atoi(thewidth->str) : 0 ) ; } else mcxTingNWrite(arg2_g, val->str, val->len) ; mcxTingNWrite(arg1_g, key->str, key->len) ; seg = expand_set_(seg, "\\set#3", bits, dict_name) ; } } while (0) ; mcxTingFree(&key) ; mcxTingFree(&val) ; mcxTingFree(&condition) ; mcxTingFree(&thestart) ; mcxTingFree(&thewidth) ; mcxTingFree(&dict_name) ; return seg->flags ? yamSegPushEmpty(seg) : seg ; } yamSeg* expandSet2 ( yamSeg* seg ) { return expand_set_(seg, "\\set#2", 0, NULL) ; } yamSeg* expandSetx2 ( yamSeg* seg ) { return expand_set_(seg, "\\setx#2", YAM_SET_EXPAND,NULL) ; } yamSeg* expandVanish1 ( yamSeg* seg ) { mcxTing* stuff = arg(arg1_g) ; mcxbits flag_zoem = yamOutput(stuff, NULL, ZOEM_FILTER_NONE) ; mcxTingFree(&stuff) ; seg_check_flag(flag_zoem, seg) ; return flag_zoem ? yamSegPushEmpty(seg) : seg ; } mcxenum let_cb ( const char* token , long *ival , double *fval ) { mcxTing* txt = mcxTingNew(token) ; mcxstatus status_let = TRM_FAIL ; mcxstatus status_zoem = yamDigest(txt, txt, NULL) ; int delta = (u8) txt->str[0] == '-' ? 1 : 0 ; if (status_zoem) { mcxTingWrite(txt, "0") ; status_let = TRM_FAIL ; } else if (mcxStrChrAint(txt->str+delta, isdigit, txt->len-delta)) { *fval = atof(txt->str) ; status_let = TRM_ISREAL ; } else { *ival = atol(txt->str) ; status_let = TRM_ISNUM ; *fval = *ival ; } mcxTingFree(&txt) ; return status_let ; } #if 0 yamSeg* expandDone0 ( yamSeg* seg ) { return yamSegPush(seg, mcxTingNew("\\throw{done}")) ; } { while (seg->prev) { yamSeg* prev_seg = seg ; seg = seg->prev ; yamSegFree(&prev_seg) ; } seg->offset = seg->txt->len ; return seg ; } #endif /* fixme; try to account for at scope as well [uh, seriously?] * (best shot should be possible simply by ignoring escape sequences). */ yamSeg* expandLength1 ( yamSeg* seg ) { mcxTing* stuff = arg(arg1_g) ; char* p ; int len = 0, c, mode = 1 ; if (yamDigest(stuff, stuff, seg)) return yamSegPush(seg, mcxTingEmpty(stuff, 0)) ; p = stuff->str ; while((c = (p++)[0])) len += (mode = (c == '\\' && mode ? 0 : 1)) ; return yamSegPush(seg, mcxTingPrint(stuff, "%d", len)) ; } yamSeg* expandLet1 ( yamSeg* seg ) { telRaam* raam = trmInit(arg1_g->str) ; long ival = 0 ; double fval = 0.0 ; mcxbool ok = FALSE ; int status = TRM_FAIL ; trmRegister(raam, checkusrcall, let_cb, '\\') ; do { if (trmParse(raam)) { yamErr("\\let#1", "expression did not parse") ; break ; } if (tracing_g & ZOEM_TRACE_LET) trmDump(raam, "let") ; status = trmEval(raam, &ival, &fval) ; if (tracing_g & ZOEM_TRACE_LET) trmDump(raam, "let") ; if (trmError(status)) { yamErr("\\let#1", "arithmetic error occurred") ; break ; } ok = TRUE ; } while (0) ; trmExit(raam) ; seg_check_ok(ok, seg) ; if (!ok) return yamSegPushEmpty(seg) ; else if (trmIsNum(status)) return yamSegPush(seg, mcxTingInteger(NULL, ival)) ; else if (trmIsReal(status)) { double fl = floor(fval+0.5) ; long l = fl ; if (fl-fval<0.0000001 && fval-fl<0.0000001) return yamSegPush(seg, mcxTingInteger(NULL, l)) ; else return yamSegPush(seg, mcxTingDouble(NULL, fval, 15)) ; } else /* huh ?? what, how, whence ?? */ return yamSegPush(seg, mcxTingInteger(NULL, 0)) ; return NULL /* unreachcode */ ; } void yamOpsStats ( void ) { mcxHashStats(stdout, yamTable_g) ; } void mod_ops_exit ( void ) { if (yamTable_g) mcxHashFree(&yamTable_g, mcxTingRelease, NULL) ; if (devtxt_g) mcxTingFree(&devtxt_g) ; if (reg_end_g) #if 0 second argument is not yet functional there. mcxListFree(®_end_g, mcxTingFree_v) #endif { mcxLink* lk = reg_end_g->next ; while (lk) { mcxTing* tg = lk->val ; mcxTingFree(&tg) ; lk = lk->next ; } mcxListFree(®_end_g, NULL) ; } ; } void mod_ops_init ( dim n ) { cmdHook* cmdhook = cmdHookDir ; srandom(mcxSeed(2308947)) ; devtxt_g = mcxTingNew("__device__") ; yamTable_g = yamHashNew(n) ; while (cmdhook && cmdhook->name) { mcxTing* cmdtxt = mcxTingNew(cmdhook->name) ; mcxKV* kv = mcxHashSearch(cmdtxt,yamTable_g,MCX_DATUM_INSERT) ; kv->val = cmdhook ; cmdhook++ ; } reg_end_g = mcxListSource(10, 0) ; } void mod_ops_digest ( void ) { mcxTing* t = mcxTingNew("\\'env{}{}{}{}") ; yamDigest(t, t, NULL) ; mcxTingFree(&t) ; } xpnfnc yamOpGet ( mcxTing* txt , const char** compositepp ) { mcxKV* kv = mcxHashSearch(txt, yamTable_g, MCX_DATUM_FIND) ; if (kv) { cmdHook* hk = kv->val ; if (hk->yamfunc) return hk->yamfunc ; *compositepp = hk->composite ; } return NULL ; } zoem-11-166/src/parse.c0000644000402500021140000006371711255254471011564 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include #include #include "parse.h" #include "ops.h" #include "source.h" #include "iface.h" #include "curly.h" #include "segment.h" #include "util.h" #include "key.h" #include "util/minmax.h" #include "util/ding.h" #include "util/inttypes.h" static const char* arg_padding_g[10] = { "#0" , "#1" , "#2" , "#3" , "#4" , "#5" , "#6" , "#7" , "#8" , "#9" } ; int tracing_g = 0; static int tracect_g = 0; mcxTing key_and_args_g[YAM_ARG_MAX+1]; mcxTing* key_g = key_and_args_g+0; mcxTing* arg1_g = key_and_args_g+1; mcxTing* arg2_g = key_and_args_g+2; mcxTing* arg3_g = key_and_args_g+3; mcxTing* arg4_g = key_and_args_g+4; mcxTing* arg5_g = key_and_args_g+5; mcxTing* arg6_g = key_and_args_g+6; mcxTing* arg7_g = key_and_args_g+7; mcxTing* arg8_g = key_and_args_g+8; mcxTing* arg9_g = key_and_args_g+9; mcxTing* arg10_g = key_and_args_g+10; int n_args_g; /* not a dim, because it engages in a few int computations */ /* no plans to support > 2147483648 (or > 32768) arguments */ mcxstatus yamParsekey ( yamSeg *line , mcxbits *keybits ) ; static int tagoffset ( const mcxTing *txt , int offset ) ; /* * -*=+H+=*-+-*=+H+=*-+-*=+H+=*-+-*=+H+=*-+-*=+H+=*-+-*=+H+=*-+-*=+H+=*- * * all zoem primitives are handled in the same way, by an expand routine. * expandUser handles all user macros. * expansion will not construct an illegal key because bsbs remains bsbs. * * If anon is true, the k from '#k' is off by one and is ignored. */ yamSeg* expandUser ( yamSeg* seg , const mcxTing* user , mcxbool anon ) { yamSeg* newseg = NULL ; mcxTing* repl = mcxTingEmpty(NULL, 30) ; int po = 0 /* previous offset */ ; int o = 0 ; int delta = anon ? 1 : 0 ; if (n_args_g) { while( (o = tagoffset(user, o)) >= 0) { int i = (uchar) *(user->str+o+1) - '0' ; mcxTingNAppend(repl, user->str+po, o-po) /* skip \k */ ; if (i < 1 || i+delta > n_args_g) { yamErr("expand", "argument \\%d out of range", i) ; mcxTingFree(&repl) ; break ; } mcxTingAppend(repl, (key_and_args_g+delta+i)->str) ; o += 2 ; po = o ; } if (o == -2) /* no closing curly */ mcxTingFree(&repl) ; } if (repl) mcxTingNAppend(repl, user->str+po, user->len-po) ; newseg = repl ? yamSegPush(seg, repl) : NULL ; return newseg ; } /* * returns l such that txt->str[offset+l] starts "\\k", k = argnum. * It skips any bang scope, i.e. \!{....} * I am not entirely sure whether this is a feature ... * Must have to do with funky k-stage nested application of keys. */ static int tagoffset ( const mcxTing *txt , int offset ) { char* o = txt->str + offset ; char* p = o ; char* z = txt->str + txt->len ; int esc = p && (*p == '\\') ; int cc ; while (++p < z) { if (esc) { if (*p >= '1' && *p <= '9') return (offset + (p-o-1)) ; else if (*p == '!') /* skip tags in delay scope */ { while (*++p == '!') NOTHING ; if (*p == '{') { cc = yamClosingCurly(txt, offset+(p-o), NULL, RETURN_ON_FAIL) ; if (cc<0) { yamErr("tagoffset", "unable to close \\! scope\n") ; return -2 ; } p += cc ; } p-- /* fixme; now *before* '}' ?? */ ; } esc = 0 ; } else if (*p == '\\') esc = 1 ; } return -1 ; } /* * returns index of '{' if it is first non-white space character, * -1 otherwise. */ int seescope ( char* p , int len ) { char* o = p ; char* z = p + len ; while(isspace((uchar) *p) && p < z) ++p ; if (*p == '{') return (p-o) ; return -1 ; } /* * returns length of key found, -1 if error occurred. */ int checkusrsig ( char* p , int len , int* kp , int* namelen_p , mcxbits* keybits_p ) { int namelen = -1 ; int taglen = -1 ; namelen = checkusrname(p, len, keybits_p) ; *namelen_p = namelen ; if (namelen <= 0) return -1 ; else if (namelen == len || *(p+namelen) != '#') /* a simple key */ { if (kp) *kp = 0 ; return namelen ; } taglen = checkusrtag(p+namelen, len-namelen, kp) ; if (taglen < 0) return -1 ; return (namelen + taglen) ; } /* * returns length of tag found, -1 if error occurred. */ int checkusrtag ( char* p , int len , int* kp ) { char* o = p /* offset */ ; uchar p0 = p[0] ; uchar p1 = len ? p[1] : 0 ; char* z = p + len ; int k = 0 ; if (p0 != '#' || !isdigit(p1) || p1 == '0') return -1 ; while (++p < z && isdigit((uchar) *p)) { k *= 10 ; k += (uchar) *p - '0' ; } if (kp) *kp = k ; return (p-o) ; } /* * returns length of block found, -1 if error occurred. */ int checkblock ( mcxTing* txt , int offset ) { int cc = yamClosingCurly(txt, offset, NULL, RETURN_ON_FAIL) ; return cc > 0 ? cc + 1 : -1 ; } /* * fixme this is used for let callback. * xml shorthand is accepted as well (which is odd). * simple additional check will remedy this. * anon routines work. */ int checkusrcall ( mcxTing* txt , int offset ) { char* a = txt->str+offset ; char* p = a ; char* z = txt->str+txt->len ; mcxbits keybits = 0 ; int len ; if (*p++ != '\\') return -1 ; if ((len = checkusrname(p, z-p, &keybits)) < 0) return -1 ; else p+=len ; if (!strncmp(a, "\\_", 2) && *p == '#' && isdigit((uchar) *(p+1))) p+= 2 ; while (1) { if (*p == '{') { if ((len = checkblock(txt, p-txt->str)) < 0) return -1 ; else p+=len ; } else break ; } return p-a ; } /* * returns length of name found, < 0 if error occurred. */ int checkusrname ( char* p , int len , mcxbits* keybits ) /* if meta set length to 1 */ { char* o = p /* offset */ ; char* z = p + len ; uchar p0 = p[0] ; uchar p1 = len ? p[1] : 0 /* XML META DATA PRIME QUOTE DOLLAR (underscore) */ ; if (len <= 0 || (!isalpha(p0) && !strchr("') if (*p == '<') /* nesting not allowed */ return -2 ; return *p == '>' ? p-o+1 : -2 ; } else if (p0 == '%') { *keybits |= KEY_DATA ; while (p++txt ; int offset = seg->offset ; int x ; char* a = txt->str ; char* o = a + offset ; char* p = a + offset ; char* z = a + txt->len ; int esc = p && (*p == '\\') ; int lc = p && (*p == '\n') ? 1 : 0 /* *p may be '\n' indeed */ ; int found = 0 ; const char* me = "yamFindKey" ; if (seg->flags & SEGMENT_CONSTANT) return -1 ; while (++p < z) { if (*p == '\n') lc++ ; if (esc) /* a backslash, that is */ { if ( isalpha((uchar) *p) || *p == '$' || *p == '_' || *p == '"' || *p == '!' || *p == '<' || *p == '>' || *p == '%' || *p == '\'' ) { found = 1 ; seg->offset = offset + (p-o-1) ; break ; } else switch(*p) { case '\\' : case '}' : case '{' : case '~' /* \~ encodes   */ : case '|' /* \| encodes
*/ : case '-' /* \- encodes &emdash; */ : case ',' /* \, is atom separator */ : case '\n' /* newline is ignored */ : case '+' /* FIXME; hacklet; at filter level */ : { esc = 0 ; break ; } /* NOTE: \& only allowed within '@' mode, * so no need to case it here */ case '@' : { p++ ; if ((uchar) p[0] == 'e') p++ ; if ((x=yamClosingCurly(txt,p-a, &lc, RETURN_ON_FAIL)) < 0) { sourceIncrLc(txt, lc) ; yamErr("yamFindKey", "error while skipping at scope") ; return -2 ; } p += x /* now *p == '}', while() will skip it */ ; esc = 0 ; break ; } case '*' : { if ((x = yamEOConstant(txt, p-a)) < 0) { yamErr(me, "format error in constant expression") ; return -2 ; } p += x /* now *p == '*', while() will skip it */ ; esc = 0 ; break ; } default : { if (*p >= '0' && *p <= '9') { esc = 0 ; break ; } else { sourceIncrLc(txt, lc) ; yamErr(me, "illegal escape sequence <\\%c>", *p) ; return -2 ; } } } ; } else if (*p == '\\') esc = 1 ; } sourceIncrLc(txt, lc) ; return (found ? seg->offset : -1) ; } /* Expects offset to match a slash introducing a keyword. Sets seg offset * beyond keyword + args. sets n_args_g, and fills key_and_args_g. padds * key with the number of arguments. * * I chose not to unify with yamParseScopes for various reasons. - * parsescopes interface would need an extra skipspace boolean, it would * probably need magic n=0 behaviour, and it would be unclear how to do the * n>9 error handling. If you need to reconsider this, think before coding. * * Caller must have set *keybits_p to zero. */ mcxstatus yamParseKey ( yamSeg *seg , mcxbits *keybits_p ) { int offset = seg->offset ; mcxTing* txt = seg->txt ; char* o = txt->str + offset ; char* z = txt->str + txt->len ; char* p = o+1 ; int n_args = 0 ; int n_anon = 0 ; int lc = 0 ; const char* me = "yamParseKey" ; int namelen = checkusrname(p, z-o-1, keybits_p) ; int keybits = *keybits_p ; if (namelen < 1) { yamErr(me, "invalid key") ; return STATUS_FAIL ; } p += namelen ; if (keybits & KEY_ANON && *p == '#') { if (*(p+1) < '1' || *(p+1) > '9' || *(p+2) != '{') { yamErr(me, "Anonymous key not ok") ; return STATUS_FAIL ; } n_anon = (uchar) *(p+1) - '0' ; p += 2 ; } if (keybits & KEY_XML) /* below hacks \> and \<{..} in */ { mcxTingWrite(key_g, "<>") ; mcxTingNWrite(arg1_g, o+2, namelen >= 2 ? namelen-2 : 0) ; lc += mcxStrCountChar(arg1_g->str, '\n', arg1_g->len) ; n_args++ ; } else if (keybits & KEY_META) { mcxTingWrite(key_g, "!") ; mcxTingNWrite(arg1_g, o+1, namelen) ; n_args++ ; } else if (keybits & KEY_DATA) { mcxTingNWrite(key_g, o+1, namelen) ; mcxTingWrite(arg1_g, "") /* initialize; append below */ ; } else if (keybits & KEY_PRIME) mcxTingNWrite(key_g,o+2, namelen-1) ; else if (keybits & KEY_GLOBAL) mcxTingNWrite(key_g,o+3, namelen-2) ; else mcxTingNWrite(key_g, o+1, namelen) ; while (p 9) { yamErr(me, "too many arguments for key %s\n", key_g->str) ; return STATUS_FAIL ; } if (keybits & KEY_DATA) mcxTingNAppend(arg1_g, p, c+1) /* do write curlies */ ; else mcxTingNWrite((key_and_args_g+n_args),p+1, c-1) ; p = p+c+1 /* position beyond closing curly */ ; if (keybits & KEY_META) /* so \!{foo}{bar} only parses \!{foo} */ break ; } sourceIncrLc(txt, lc) ; lc = 0 ; if (n_anon && n_anon + 1 != n_args) { yamErr ( me , "found anon _#%d{%s} with %d arguments" , n_anon , arg1_g->str , n_args - 1 ) ; return STATUS_FAIL ; } else if (keybits & KEY_DATA) mcxTingAppend(key_g, "#1") ; else if (n_args) mcxTingAppend(key_g, arg_padding_g[n_args]) ; n_args_g = n_args ; seg->offset = offset + (p-o) ; return 0 ; } yamSeg* yamDoKey ( yamSeg *seg ) { mcxbits keybits = 0 ; if (yamParseKey(seg, &keybits)) return NULL ; return yamExpandKey(seg, keybits) ; } int yamCountScopes ( mcxTing* txt , int offset ) { char* p = txt->str+offset ; char* o = p ; char* z = txt->str+txt->len ; char* q = mcxStrChrAint(o, isspace, z-o) ; int count = 0 ; if (q && '{' == (uchar) *q) while(1) { int cc /* closing curly */ ; if (!(p = mcxStrChrAint(p, isspace, z-p))) p = z ; if (p==z || *p != '{') break ; if ((cc=yamClosingCurly(txt, offset + p-o, NULL, RETURN_ON_FAIL)) < 0) { yamErr("yamCountScopes", "cannot close scope") ; return -2 ; } count++ ; p += cc + 1 ; } else p = z ; if (q && !count) count = -1 ; if (p != z) { /* yamErr("yamCountScopes", "found stuff trailing") */ ; return -2 ; } return count ; } /* */ char* yamParseKV ( yamSeg* segkv ) { yamSeg* segops ; mcxTing* val ; char* key ; int x, y ; x = yamParseScopes(segkv, 2, 0) ; n_args_g = 0 ; if (x <= 0) return NULL ; key = mcxStrDup(arg1_g->str) ; if (x == 1) return key /* caller should check n_args_g */ ; val = mcxTingNNew(arg2_g->str, arg2_g->len) ; segops = yamStackPushTmp(val) ; y = yamParseScopes(segops, YAM_ARG_MAX, 0) ; if (!y || y < 0) n_args_g = 0 ; yamStackFreeTmp(&segops) ; mcxTingFree(&val) ; return key ; } /* * returns number of scopes found, possibly less than n. */ int yamParseScopes ( yamSeg* seg , int n , int delta ) { int offset = seg->offset ; mcxTing* txt = seg->txt ; char* o = txt->str + offset ; char* p = o ; char* z = txt->str + txt->len ; char* q = mcxStrChrAint(o, isspace, z-o) ; int count = 0 ; if (delta + n > YAM_ARG_MAX) yamErrx(1, "yamParseScopes PBD", "not that many (%d) scopes allowed", n) ; if (tracing_g & (ZOEM_TRACE_SCOPES)) printf(" sco| parsing up to %d scopes\n", n) ; if (q && '{' == (uchar) *q) while(count < n) { int cc /* closing curly */ ; if (!(p = mcxStrChrAint(p, isspace, z-p))) p = z ; if (p==z || *p != '{') break ; if ((cc=yamClosingCurly(txt, offset + p-o, NULL, RETURN_ON_FAIL)) < 0) { yamErr("yamParseScopes", "cannot close scope") ; return -1 /* mq: seg->offset ok? */ ; } mcxTingNWrite(key_and_args_g+(delta + ++count), p+1, cc-1) ; p += cc + 1 ; if (tracing_g & (ZOEM_TRACE_SCOPES)) traceput("sco", key_and_args_g+delta+count) ; } else if (q) { mcxTingNWrite(key_and_args_g+(delta + ++count), o, z-o) ; p = z ; if (tracing_g & (ZOEM_TRACE_SCOPES)) traceput("sco", key_and_args_g+delta+count) ; } if (tracing_g & (ZOEM_TRACE_SCOPES)) printf(" sco| found %d scopes\n", count) /* caller should fill key_g */ ; n_args_g = count + delta ; seg->offset = offset + p-o ; return count ; } /* * Is called after yamParseKey in yamDoKey. yamParseKey fills key_and_args_g * and updates seg->offset. * Pops a new seg onto the stack. */ yamSeg* yamExpandKey ( yamSeg *seg , mcxbits keybits ) { const char* composite = NULL ; mcxTing* user = keybits & KEY_ANON ? arg1_g : keybits & KEY_PRIME ? NULL : keybits & KEY_GLOBAL ? yamKeyGetGlobal(key_g) : yamKeyGet(key_g) ; xpnfnc yamop = NULL ; if (tracing_g) { int i ; tracect_g++ ; if (tracing_g & ZOEM_TRACE_KEYS) printf ( "%s|%-32s seg %2d stack %2d nr %6d\n" , user ? "# #" : " ## " , key_g->str , seg->idx , yamStackIdx() , tracect_g ) ; if (user && (tracing_g & (ZOEM_TRACE_DEFS))) traceput("def", user) ; if (tracing_g & (ZOEM_TRACE_ARGS)) { for (i=1;i<=n_args_g;i++) traceput("arg", key_and_args_g+i) ; } ; } if (user) return expandUser(seg, user, keybits & KEY_ANON) ; if (!(keybits & KEY_GLOBAL)) yamop = yamOpGet(key_g, &composite) /* docme wth is this */ ; if ( tracing_g & ZOEM_TRACE_PRIME && !(keybits & KEY_PRIME) && !strchr("<>!%", (uchar) key_g->str[0]) ) traceput("zum", key_g) ; if (yamop) return yamop(seg) /* fixme: initialize tings somewhere */ ; else if (composite) { mcxTing* comp = mcxTingNew(composite) ; yamSeg* newseg = expandUser(seg, comp, FALSE) ; mcxTingFree(&comp) ; return newseg ; } else yamErr ( "expand" , "no definition found for %s <%s>" , keybits & KEY_PRIME ? "primitive" : "key" , key_g->str ) ; return NULL ; } void mod_parse_exit ( void ) { int i ; for(i=0;istr ; int l = txt->len ; char* nl = strchr(s, '\n') ; int i_nl = nl ? nl - s : l ; int LEN = 50 ; char* cont ; int n ; n = MCX_MAX(0, MCX_MIN(i_nl, MCX_MIN(l, LEN))) ; cont = nl && i_nl < LEN ? "(\\n)" : nl && i_nl >= LEN ? "(..\\n)" : n < l ? "(..)" : "" ; if (tracing_g & (ZOEM_TRACE_LONG)) { printf("(%s(", c) ; traceputlines(s, -1) ; } else printf("(%s)%.*s%s [%d]\n", c, n, s, cont, l) ; } void traceputlines ( const char* s , int len ) { const char* z = len >= 0 ? s + len : NULL ; while (*s && (!z || s < z)) { if (*s == '\n') printf("\n |") ; else putc(*s, stdout) ; s++ ; } fputs("$\n) )\n", stdout) ; } void yamScratchStats ( void ) { int i ; fprintf(stderr, "key .......: <%lu>\n", (ulong) key_g->mxl) ; for (i=1;i<10;i++) fprintf(stderr, "arg <%d> ...: <%lu>\n", i, (ulong) (key_and_args_g+i)->mxl) ; } yamSeg* yamFormatted1 ( yamSeg* seg , const char* arg ) { mcxTing* txt = mcxTingNew(arg) ; char* o = txt->str ; char* p = o ; char* q = o ; char* z = o + txt->len ; mcxbool formatting = TRUE ; mcxbool ok = TRUE ; int esc = 0 ; while (p < z) { if (esc) { if ((uchar) p[0] == '@') /* fixme uggggglyyyyyy */ { int l ; if ((uchar) p[1] == 'e') p++ ; l = yamClosingCurly(txt, p+1-o, NULL, RETURN_ON_FAIL) ; if (l<0) { ok = FALSE ; goto done ; } *(q++) = '\\' ; *(q++) = '@' ; if ((uchar) p[0] == 'e') *(q++) = 'e' ; while (l-- && ++p) /* write '{' upto-exclusive '}' */ *(q++) = *p ; *(q++) = *++p /* writes the '}' */ ; } else if (*p == '<') /* fixme UGGGGGLYYYYYY */ { int l = yamClosingCube(txt, p-o, NULL, RETURN_ON_FAIL) ; if (l<0) { ok = FALSE ; goto done ; } *(q++) = '\\' ; *(q++) = '<' ; while (l-- && ++p) /* write after '<' upto-inclusive '>' */ *(q++) = *p ; } else if (*p == '`') /* ugly branch, still supporting old syntax */ { const char* pp = p+1 ; int x = 0 ; if ((uchar) pp[0] == '{') x = yamClosingCurly(txt,pp-txt->str, NULL, RETURN_ON_FAIL) ; if (x < 0) { ok = FALSE ; goto done ; } else if (x > 0) p = p+1 ; while (1) { ++p ; if ( (x > 0 && p-pp >= x) || p >= z || (x == 0 && *(p) == '`') ) break ; switch(*p) { case 's' : case ' ' : *(q++) = ' ' ; break ; case 'n' : case '\n' : *(q++) = '\n' ; break ; case 't' : case '\t' : *(q++) = '\t' ; break ; case '[' : case '<' : formatting = FALSE ; break ; case ']' : case '>' : formatting = TRUE ; break ; default : yamErr("\\formatted1", "illegal character <%c>", *p) ; ok = FALSE ; goto done ; } } if (x == 0) { static long n_bq_deprecated = 0 ; if (p == z) { yamErr("\\formatted1", "missing close symbol") ; goto done ; } if (!n_bq_deprecated++) yamErr ( "zoem" , "deprecated: \\`%.*s`, use \\`{%.*s} instead" , (int) (p-pp) , pp , (int) (p-pp) , pp ) ; } } else if (*p == ':') do { p++; } while (plen = q-o ; return yamSegPush(seg, txt) ; } zoem-11-166/src/read.c0000644000402500021140000004445611576077736011401 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include #include /* getenv */ #include #include #include #include #include #include #include #include #include "filter.h" #include "read.h" #include "source.h" #include "parse.h" #include "iface.h" #include "segment.h" #include "curly.h" #include "util.h" #include "key.h" #include "util/io.h" #include "util/hash.h" #include "util/types.h" #include "util/getpagesize.h" #include "util/err.h" #include "util/ding.h" #include "util/tr.h" static mcxHash* mskTable_g = NULL; /* masked input files*/ /* * This code also finds and stores inline files. * It is not error/memory clean and contains hard exits. * * fixme does line count compensation work when chunks land inbetween * \:/ lines? or do chunks never do that? */ #define DEBUG 0 mcxstatus yamReadChunk ( mcxIO *xf /* must be open! */ , mcxTing *filetxt , mcxbits flags , int chunk_size /* if 0, try to read everything */ , long *n_lines_read , void (*lcc_update)(long n_deleted, long n_lines, void* data) , void* data ) { mcxbool am_inline = flags & READ_INLINE ; mcxTing* line = mcxTingEmpty(NULL, 160) ; int level = 0 ; size_t bytes_read = 0 /* size_t bytes_offset= xf->bc */ ; const char* me = "zoem input" ; mcxstatus stat = STATUS_DONE ; int n_deleted = 0 ; filetxt = mcxTingEmpty(filetxt, 0) ; while ( STATUS_OK == (stat = mcxIOreadLine(xf, line, MCX_READLINE_DEFAULT))) { int discardcmt = 0, esc = 0 ; char* a = line->str, *p = a, *z = a + line->len, *P = NULL ; mcxbool inline_file_token = strncmp(line->str, "\\=", 2) ? 0 : 1 ; (*n_lines_read)++ ; if (!inline_file_token) { while (pstr) ; bytes_read += line->len /* fixme: also need to do this in case chunk is finished. * (is this fixme still relevant and what is it about?) */ ; if (n_deleted && discardcmt != 2) /* so if range has finished */ { if (lcc_update) lcc_update(n_deleted, *n_lines_read, data) ; n_deleted = 0 ; } } if (inline_file_token && !am_inline) { mcxKV *kv ; mcxTing *fname = NULL, *masked = mcxTingEmpty(NULL, 1000) ; long n_lines_read_inline = 0 ; int l = 0 ; fname = yamBlock(line, 2, &l, NULL) ; if (!fname) yamErrx(1, me, "format err in \\={fname} specification") ; kv = mcxHashSearch(fname, mskTable_g, MCX_DATUM_INSERT) ; if (kv->key != fname) yamErrx(1, me, "file <%s> already masked", fname->str) ; mcxTell(me, "=== reading am_inline file <%s>", fname->str) ; if ( STATUS_DONE == yamReadChunk (xf, masked, READ_INLINE, 0, &n_lines_read_inline, NULL, NULL) ) { kv->val = masked ; lcc_update (n_lines_read_inline+1, *n_lines_read+n_lines_read_inline+1, data) ; *n_lines_read += n_lines_read_inline ; continue ; } else yamErrx(1, me, "error reading am_inline file <%s>", fname->str) ; } else if (inline_file_token && am_inline) { mcxTell(me, "=== done reading am_inline file") ; if (line->str[2] != '=') yamErrx(1, me, "expecting closing '\\==' at line <%d>",xf->lc) ; mcxTingFree(&line) ; return STATUS_DONE /* fixme; move this return to end */ ; } if (level < 0) mcxErr ( me , "Curly underflow in file <%s> at line <%ld>" , xf->fn->str , (long) xf->lc ) , level = 0 ; if ( !am_inline && chunk_size && bytes_read >= chunk_size && discardcmt != 2 && level <= 0 ) { stat = STATUS_OK ; if (n_deleted) /* tidy up */ lcc_update(n_deleted, *n_lines_read, data) ; break ; } } mcxTingFree(&line) #if DEBUG ; fprintf(stderr, "read <%ld> bytes\n", (long) xf->bc) #endif ; if (am_inline) yamErrx(1, me, "inline file scope not closed!\n") ; return stat ; } void mod_read_init ( int n ) { mskTable_g = yamHashNew(n) ; } void mod_read_exit ( void ) { if (mskTable_g) mcxHashFree(&mskTable_g, mcxTingRelease, mcxTingRelease) ; } const mcxTing* yamInlineFile ( mcxTing* fname ) { mcxKV* kv = mskTable_g ? mcxHashSearch(fname, mskTable_g, MCX_DATUM_FIND) : NULL ; return kv ? (mcxTing*)kv->val : NULL ; } void yamUnprotect ( mcxTing* txt ) { char* p = txt->str ; char* q = txt->str ; int esc= 0 ; while(pstr+txt->len) { if (esc) { if (*p == '\\' || *p == '{' || *p == '}') *(q++) = *p ; else { *(q++) = '\\' ; *(q++) = *p ; } esc = 0 ; } else if (*p == '\\') esc = 1 ; else *(q++) = *p ; p++ ; } *q = '\0' ; txt->len = q-txt->str ; } mcxTing* yamProtect ( mcxTing* data ) { dim i = 0 ; dim j = 0 ; int n = data->len + (data->len/8) ; mcxTing* protected = mcxTingEmpty(NULL, n) ; for(i=0;ilen;i++) { char c = *(data->str+i) ; int esc = (c == '\\' || c == '{' || c == '}') ? 1 : 0 ; if (j+esc >= protected->mxl) mcxTingEnsure(protected, protected->mxl + (protected->mxl/3) + 2) ; if (esc) *(protected->str+j++) = '\\' ; *(protected->str+j++) = c ; } protected->len = j ; *(protected->str+j) = '\0' ; return protected ; } mcxTing* yamReadData ( mcxIO *xf , mcxTing *filetxt ) #define BUFLEN 1024 { char cbuf[BUFLEN] ; short c ; int i = 0 ; if (!xf->fp) mcxIOerr(xf, "yamReadData PBD", "is not open") , mcxExit(1) ; filetxt = mcxTingEmpty(filetxt, 0) ; while ( c = mcxIOstep(xf) , c != EOF ) { if (c == '\\' || c == '{' || c == '}') cbuf[i++] = (char) '\\' ; cbuf[i] = (char) c ; if (i+2 >= BUFLEN) /* if not, no room for double bs */ { mcxTingNAppend(filetxt, cbuf, i+1) ; i = 0 ; continue ; } i++ ; } if (i) /* nothing written at this position */ mcxTingNAppend(filetxt, cbuf, i) ; xf->ateof = 1 ; return filetxt #undef BUFLEN ; } mcxIO* yamRead__open_file__ ( const char* name ) { mcxIO *xf = mcxIOnew(name, "r") ; if (mcxIOopen(xf, RETURN_ON_FAIL) == STATUS_OK) return xf ; else mcxIOfree(&xf) ; return NULL ; } /* * I had some trouble getting the details right. These are the different * cases that once caused trouble: Assume a file t.azm containing * * \write{bar}{txt}{1 2 3 4 hoedje van papier} * \system{date}{}{} * \system{date}{}{} * \system{date}{}{} * \system{date}{}{} * * and consider the command lines * * zoem -i t -o - * zoem -i t -o foo * zoem -i t -o - > foo * * All these cases were buggy under different circumstances; pipe ends need * to be closed, data needs to be flushed, and open file descriptors * need to be closed. */ mcxTing* yamSystem ( char* cmd , char* argv[] , mcxTing* data ) #define LDB (tracing_g & ZOEM_TRACE_SYSTEM) #define RB_SIZE 4096 { int stat1, stat2, xstat, k ; int fx[2] ; int fy[2] ; pid_t cp1, cp2 ; char rb[RB_SIZE] ; int statusx = pipe(fx) ; int statusy = pipe(fy) ; if (statusx || statusy) { yamErr("\\system#3", "pipe error") ; perror("\\system#3") ; return NULL ; } yamUnprotect(data) ; if (fflush(NULL)) perror("flush") ; cp1 = fork() ; if (cp1 == -1) /* error */ { yamErr("\\system#3", "fork error") ; perror("\\system#3") ; return NULL ; } else if (cp1 == 0) /* child */ { if (LDB) printf(" sys| CHILD closing x1=%d and y0=%d\n", (int) fx[1], (int) fy[0]) ; if (close(fx[1])<0) perror("close fx[1]") /* close parent output */ ; if (close(fy[0])<0) perror("close fy[0]") /* close child input */ ; if (LDB) { printf(" sys| CHILD mapping %d to %d\n",(int)fx[0], (int) fileno(stdin)) ; printf(" sys| CHILD mapping %d to %d\n",(int)fy[1], (int) fileno(stdout)) ; } dup2(fx[0], fileno(stdin)) ; dup2(fy[1], fileno(stdout)) ; if (close(fx[0])<0) perror("close fx[0]") ; if (close(fy[1])<0) perror("close fy[1]") ; switch ((cp2 = fork())) { case -1 : perror("fork") ; exit(1) ; case 0 /* grandchild */ : execvp(cmd, argv) /* do the actual stuff */ ; yamErrx(1, "\\system#3", "exec <%s> failed (bummer)", cmd) ; break ; default /* child */ : if(0)fprintf(stderr, "START child\n") ; if (waitpid(cp2, &stat2, 0)< 0 || !WIFEXITED(stat2)) { if (0) /* unreachcode */ perror("child") ; } while (0 && (k = read(fileno(stdin), rb, RB_SIZE))) { if (LDB) fprintf ( stderr ," sys| CHILD discarding %d bytes\n", (int) k ) ; } /* The discard loop is for this: * \system{cat}{{-#}}{abcdef} (i.e. failing command) * we need someone to read the stdin, lest we get a broken pipe. * (and we want \system never to fail in zoem). */ /* Do I need the close below? e.g. wrt 'zoem -i t -o - > foo'. * Not too clear on these issues, but it seems best * practice to close all pipe ends when done. */ ; if (close(fileno(stdin))<0) perror("close fileno(stdin)") ; if (close(fileno(stdout))<0) perror("close fileno(stdout)") ; if (stat2) yamErr("\\system#3", "child <%s> failed", cmd) ; exit(stat2 ? 1 : 0) ; } } else /* parent */ { mcxTing* buf = mcxTingEmpty(NULL, 80) ; mcxTing* res = NULL ; static int ct = 0 ; if (LDB) printf (" sys| PARENT closing x0=%d and y1=%d\n", (int) fx[0], (int) fy[1]) ; close(fy[1]) /* close output */ ; close(fx[0]) /* close input */ ; if (data->len) /* mq, must not exceed buffer size */ { fprintf(stderr, "<%d> bytes written\n", (int) data->len) ; write(fx[1], data->str, data->len) ; } close(fx[1]) ; ct++ ; while ((k = read(fy[0], rb, RB_SIZE))) { if (k<0) { perror("read") ; break ; } if (buf->len + k > buf->mxl) mcxTingEnsure(buf, buf->mxl + buf->mxl/2) ; mcxTingNAppend(buf, rb, k) ; } close(fy[0]) ; if ((waitpid(cp1, &stat1, 0)) < 0 || !WIFEXITED(stat1)) perror("waiting parent") ; xstat = WIFEXITED(stat1) ? WEXITSTATUS(stat1) : 1 ; yamKeySet("__sysval__", xstat ? "1" : "0") ; if (!xstat) res = yamProtect(buf) ; else res = NULL ; mcxTingFree(&buf) ; if (res) { while ( res && res->len && isspace((unsigned char) res->str[res->len-1]) ) res->len -= 1 ; res->str[res->len] = '\0' ; } ; return res ; } return NULL ; } #undef LDB #undef RB_SIZE mcxIO* yamTryOpen ( mcxTing* fname , const mcxTing** inline_txt_ptr , mcxbool useSearchPath ) #define LDB (tracing_g & ZOEM_TRACE_IO) { mcxIO *xf = NULL ; mcxTing* file = NULL ; char* envp ; char* wherefound = "nowhere" ; if (fname->len > 1024) { yamErr("yamTryOpen", "input file name expansion too long (>1024)") ; *inline_txt_ptr = NULL ; return NULL ; } /* . first check inline file * . then check file name as is. * . then check $ZOEMSEARCHPATH * . then check __searchpath__ * . then check sourceGetPath (last file openened) */ /* .. then we may look for inline files */ if (inline_txt_ptr) { const mcxTing* filetxt = yamInlineFile(fname) ; if (filetxt) { *inline_txt_ptr = filetxt ; if (LDB) mcxTell(NULL, "=== using inline file <%s>", fname->str) ; return mcxIOnew(fname->str, "r") ; } } if (LDB) printf("| trying (cwd) <%s>\n", fname->str) ; xf = yamRead__open_file__(fname->str) ; if (xf) wherefound = "in current working directory" /* * Try to find a readable file in a few more places. */ ; if (!xf && useSearchPath && (envp = getenv("ZOEMSEARCHPATH"))) { mcxTing* zsp = mcxTingNew(envp) ; char *q, *p = zsp->str ; mcxTingTr(zsp, ":[:space:]", " [* *]", NULL, "[:space:]", 0) ; file = mcxTingEmpty(file, 30) ; while (p) { while (isspace((unsigned char) *p)) p++ ; q = mcxStrChrIs(p, isspace, -1) ; if (q) mcxTingNWrite(file, p, q-p) ; else mcxTingWrite(file, p) ; if (file->len && file->str[file->len-1] != '/') mcxTingAppend(file, "/") ; mcxTingAppend(file, fname->str) ; if (LDB) printf("| trying (env) <%s>\n", file->str) ; if ((xf = yamRead__open_file__(file->str))) { mcxTingWrite(fname, file->str) ; wherefound = file->str ; break ; } p = q ; } mcxTingFree(&zsp) ; } if (!xf && useSearchPath) { mcxTing* tmp = mcxTingNew("__searchpath__") ; mcxTing* sp = yamKeyGet(tmp) ; yamSeg* spseg = sp ? yamStackPushTmp(sp) : NULL ; file = mcxTingEmpty(file, 30) ; while (sp && yamParseScopes(spseg, 1, 0) == 1) { mcxTingPrint(file, "%s/%s", arg1_g->str, fname->str) ; if (LDB) printf("| trying (var) <%s>\n", file->str) ; if ((xf = yamRead__open_file__(file->str))) { mcxTingWrite(fname, file->str) ; wherefound = file->str ; break ; } } mcxTingFree(&tmp) ; yamStackFreeTmp(&spseg) ; } if (!xf) { mcxTingFree(&file) /* ugly hack ensuring memcleannes */ ; file = sourceGetPath() ; if (file) { mcxTingAppend(file, fname->str) ; if (LDB) printf ("| trying (his) <%s> path stripped from last include\n" , file->str ) ; if ((xf = yamRead__open_file__(file->str))) mcxTingWrite(fname, file->str) , wherefound = file->str ; } } if (LDB) printf("| found %s\n", wherefound) ; mcxTingFree(&file) ; return xf ; } zoem-11-166/src/segment.c0000644000402500021140000001031210722562514012071 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include "segment.h" #include "util.h" #include "iface.h" #include "parse.h" #include "digest.h" /* for STATUS_THROW only, move that someplace else */ #include "zlimits.h" #include "util/ting.h" #include "util/alloc.h" #include "util/gralloc.h" static int segment_depth_max = 200; static int stackidx_g = -1; static int stack_depth_max = 100; static mcxGrim* src_seg_g = NULL; void yamSegUlimit ( int segment , int stack ) { if (segment >= 0) segment_depth_max = segment ; if (stack >= 0) stack_depth_max = stack ; } int yamStackIdx ( void ) { return stackidx_g ; } void yamSegFree ( yamSeg **segpp ) { yamSeg* seg = *segpp ; if (!seg) return ; if (seg->idx && !seg->txt) yamErrx(1, "yamSegFree PBD", "no txt at seg idx <%d>\n", seg->idx) ; if (seg->idx) /* the first segment txt is not freed */ mcxTingFree(&(seg->txt)) ; if (!seg->prev) stackidx_g-- ; mcxGrimLet(src_seg_g, seg) ; *segpp = NULL ; } void yamSegInit ( yamSeg* this_seg , mcxTing* txt ) { this_seg->txt = txt ; this_seg->prev = NULL ; this_seg->offset = 0 ; this_seg->idx = 0 ; this_seg->flags = 0 ; } yamSeg* yamStackPush ( mcxTing* txt ) { yamSeg* newseg = yamSegPush(NULL, txt) ; stackidx_g++ ; if (stack_depth_max && stackidx_g > stack_depth_max) { yamErr ( "yamStackPush" , "exceeding maximum stack depth <%d>" , stack_depth_max ) ; newseg->flags |= SEGMENT_ERROR ; } return newseg ; } void yamStackFree ( yamSeg **segpp ) { yamSeg* seg = *segpp ; if (!seg) return ; while(seg) { yamSeg* down = seg->prev ; yamSegFree(&seg) ; seg = down ; } ; } yamSeg* yamStackPushTmp ( mcxTing* txt ) { yamSeg* newseg ; stack_depth_max++ ; newseg = yamStackPush(txt) ; return newseg ; } void yamStackFreeTmp ( yamSeg **segpp ) { yamStackFree(segpp) ; stack_depth_max-- ; } yamSeg* yamSegPushEmpty ( yamSeg* prevseg ) { return yamSegPush(prevseg, mcxTingEmpty(NULL, 0)) ; } yamSeg* yamSegPush ( yamSeg* prevseg , mcxTing* txt ) { yamSeg* next_seg = mcxGrimGet(src_seg_g) ; int new_idx = prevseg ? prevseg->idx + 1 : 0 ; int new_flags = prevseg ? prevseg->flags : 0 /* don't print the entire entry file grm: we still print other files * fixmefixme */ ; if (tracing_g & ZOEM_TRACE_SEGS && (new_idx || stackidx_g)) { fprintf(stdout, " seg| %d stack %d\n", new_idx, stackidx_g) ; traceput("dat", txt) ; } next_seg->txt = txt ; next_seg->offset = 0 ; next_seg->idx = new_idx ; next_seg->prev = prevseg ; next_seg->flags = new_flags ; if (segment_depth_max && new_idx > segment_depth_max) { yamErr ( "yamSegPush" , "exceeding maximum segment depth <%d>" , segment_depth_max ) ; next_seg->flags |= SEGMENT_ERROR ; } return next_seg ; } yamSeg* yamSegPushx ( yamSeg* prevseg , mcxTing* txt , int flags ) { yamSeg* newseg = yamSegPush(prevseg, txt) ; newseg->flags = prevseg->flags | flags ; return newseg ; } /* set error if not already error or throw by digestion */ void seg_check_ok ( mcxbool ok , yamSeg* seg ) { if (!ok && !(seg->flags & SEGMENT_INTERRUPT)) seg->flags |= SEGMENT_ERROR ; } void seg_check_flag ( mcxbits flag_zoem , yamSeg* seg ) { if (seg->flags & SEGMENT_INTERRUPT) /* already set */ return ; seg->flags |= flag_zoem ; } void mod_segment_init ( void ) { src_seg_g = mcxGrimNew(sizeof(yamSeg), 40, MCX_GRIM_ARITHMETIC) ; } void mod_segment_exit ( void ) { mcxGrimFree(&src_seg_g) ; } zoem-11-166/src/util.c0000644000402500021140000001266010743355673011425 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include #include "util.h" #include "segment.h" #include "key.h" #include "ops.h" #include "source.h" #include "digest.h" #include "parse.h" #include "util/ting.h" #include "util/err.h" #include "util/hash.h" #include "util/types.h" #include "util/alloc.h" #include "util/list.h" #include "util/io.h" static FILE* fperr = NULL; static u32 (*tinghash_g)(const void* str) = mcxTingFNVhash; mcxstatus yamHashFie ( const char* id ) { if (!(tinghash_g = mcxTingHFieByName(id))) return STATUS_FAIL ; return STATUS_OK ; } mcxHash* yamHashNew ( dim n ) { return mcxHashNew(n, tinghash_g, mcxTingCmp) ; } void yamErrorFile ( FILE* fp ) { fperr = fp ; } void yamStats ( void ) { fprintf(stdout, "Zoem user table stats\n") ; yamKeyStats() ; fprintf(stdout, "Zoem primitive table stats\n") ; yamOpsStats() ; fprintf(stdout, "Scratch lengths\n") ; yamScratchStats() ; } void yam_err_ ( const char *caller , const char *fmt , va_list *args ) { const char* fname = sourceGetName() ; FILE* fp = fperr ? fperr : stderr ; if (*fname) mcxErrf ( fp , "zoem" , "error around input line <%ld> in <%s>" , sourceGetLc() , fname ) ; else mcxErrf ( fp , "zoem" , "error occurred" ) ; if (key_g->str) mcxErrf(fp, NULL, "last key seen is <%s>", key_g->str) ; if (caller) fprintf(fp, "___ [%s] ", caller) ; else fprintf(fp, "___ ") ; vfprintf(fp, fmt, *args) ; fprintf(fp, "\n") ; } void yamErrx ( int status , const char *caller , const char *fmt , ... ) { va_list args ; va_start(args, fmt) ; yam_err_(caller, fmt, &args) ; va_end(args) ; if (status) mcxExit(status) ; } void yamErr ( const char *caller , const char *fmt , ... ) { va_list args ; va_start(args, fmt) ; yam_err_(caller, fmt, &args) ; va_end(args) ; } void ting_stack_push ( lblStack* st , char* str , int len ) { mcxLink* lk = st->sp ; lk = lk->next ? lk->next : mcxLinkAfter(lk, NULL) ; lk->val = mcxTingNWrite(lk->val, str, len) /* fixme (NULL return) */ ; st->sp = lk ; } const char* ting_stack_pop ( lblStack* st ) { const char* str = NULL ; mcxLink* lk = st->sp ; if (lk->prev) { str = ((mcxTing*) lk->val)->str ; lk = lk->prev ; st->sp = lk ; } return str ; } void ting_stack_free ( lblStack** stackp ) { lblStack* stack = *stackp ; mcxLink* lk = stack->sp ; mcxTing* t ; while (lk->next) lk = lk->next ; while (lk->prev) t = (mcxTing*) lk->val , mcxTingFree(&t) , lk = lk->prev ; mcxListFree(&lk, NULL) ; mcxFree(stack) ; *stackp = NULL ; } lblStack* ting_stack_new ( int capacity ) { lblStack* stack = mcxAlloc(sizeof(stack), EXIT_ON_FAIL) ; stack->sp = mcxListSource(capacity, MCX_GRIM_ARITHMETIC) ; return stack ; } void ting_stack_init ( lblStack* stack , int capacity ) { stack->sp = mcxListSource(capacity, MCX_GRIM_ARITHMETIC) ; } /* TODO */ void ting_tilde_expand ( mcxTing* pat , mcxbits modes ) { char* a = pat->str ; char* b = a ; mcxbool esc = FALSE ; mcxbool ux = modes & YAM_TILDE_UNIX ; mcxbool rx = modes & YAM_TILDE_REGEX ; while (a < pat->str+pat->len) { if (!esc && (unsigned char) *a == '~') { esc = TRUE ; a++ ; continue ; } if (!esc) *b = *a ; else { mcxbool match = TRUE ; if (ux) /* future: \C^A for control-A. */ switch ((unsigned char) *a) { case '~' : *b = '~' ; break ; case 'E' : *b = '\\' ; *++b = '\\' ; break ; case 'I' : *b = '\\' ; *++b = '{' ; break ; case 'J' : *b = '\\' ; *++b = '}' ; break ; case 'e' : *b = '\\' ; break ; case 'i' : *b = '{' ; break ; case 'j' : *b = '}' ; break ; case 'a' : case 'b' : case 'f' : case 'n' : case 'r' : case 't' : case 'v' : case '0' : case '1' : case '2' : case '3' : case 'x' /* zoem feature */ : *b = '\\' ; *++b = *a ; break ; default : match = FALSE ; break ; } if (!match && rx) switch ((unsigned char) *a) { case '^' : case '.' : case '[' : case '$' : case '(' : case ')' : case '|' : case '*' : case '+' : case '?' : *b = '\\' ; *++b = *a ; break ; default : *b = *a ; break ; } else if (!match) *b = *a ; esc = FALSE ; } a++ ; b++ ; } pat->len = b - pat->str ; *b = '\0' ; } zoem-11-166/src/zoem.c0000644000402500021140000004046311576074470011422 00000000000000/* (C) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen * * This file is part of Zoem. You can redistribute and/or modify Zoem under the * terms of the GNU General Public License; either version 3 of the License or * (at your option) any later version. You should have received a copy of the * GPL along with Zoem, in the file COPYING. */ #include #include #include #include "entry.h" #include "iface.h" #include "util.h" #include "ops.h" #include "version.h" #include "key.h" #include "sink.h" #include "filter.h" #include "util/io.h" #include "util/opt.h" #include "util/ting.h" #include "util/types.h" #include "util/alloc.h" #include "util/err.h" #include "util/minmax.h" const char *zoemVersion = "zoem %s\n" "(c) Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 Stijn van Dongen.\n" "(c) Copyright 2008, 2009, 2010, 2011 Stijn van Dongen.\n" "zoem comes with NO WARRANTY to the extent permitted by law.\n" "You may redistribute copies of zoem under the terms\n" "of the GNU General Public License.\n" ; const char* syntax = "Usage: zoem [-i fname[.azm]] [-d device] [options]"; enum { MY_OPT_OUTPUT , MY_OPT_INPUT , MY_OPT_input , MY_OPT_DEVICE , MY_OPT_SET = MY_OPT_DEVICE + 2 , MY_OPT_EXPR , MY_OPT_EXPR_EXIT , MY_OPT_SPLIT , MY_OPT_CHUNK , MY_OPT_X , MY_OPT_HELP = MY_OPT_X + 2 , MY_OPT_APROPOS , MY_OPT_LIST , MY_OPT_ALLOW = MY_OPT_LIST + 2 , MY_OPT_UNSAFE , MY_OPT_UNSAFE_SILENT , MY_OPT_SYSTEM_HONOR , MY_OPT_STRESS_WRITE = MY_OPT_SYSTEM_HONOR + 2 , MY_OPT_ERR_OUT , MY_OPT_TRACE , MY_OPT_TTRACE , MY_OPT_VERSION , MY_OPT_NORL , MY_OPT_TL , MY_OPT_TRACE_KEYS , MY_OPT_TRACE_REGEX , MY_OPT_TRACE_ALL_SHORT , MY_OPT_TRACE_ALL_LONG , MY_OPT_STATS , MY_OPT_NSEGMENT = MY_OPT_STATS + 2 , MY_OPT_NSTACK , MY_OPT_NUSER , MY_OPT_NENV , MY_OPT_AMOIXA = MY_OPT_NENV + 2 , MY_OPT_AMCS , MY_OPT_AMIC , MY_OPT_HF , MY_OPT_BUSER , MY_OPT_BZOEM } ; mcxOptAnchor options[] = { { "-o" , MCX_OPT_HASARG , MY_OPT_OUTPUT , "" , "specify output file name, explicitly" } , { "-i" , MCX_OPT_HASARG , MY_OPT_input , "" , "specify 'azm' suffixed input file" } , { "-I" , MCX_OPT_HASARG , MY_OPT_INPUT , "" , "specify input file" } , { "-d" , MCX_OPT_HASARG , MY_OPT_DEVICE , "" , "set zoem key \\__device__ to )" } , { "-s" , MCX_OPT_HASARG , MY_OPT_SET , "" , "set zoem key to (repeated use allowed)" } , { "-e" , MCX_OPT_HASARG , MY_OPT_EXPR_EXIT , "" , "evaluate any (stdout output) and exit" } , { "-E" , MCX_OPT_HASARG , MY_OPT_EXPR , "" , "evaluate any (stdout output) and proceed" } , { "-x" , MCX_OPT_DEFAULT , MY_OPT_X , NULL , "if error occurs, enter interactive mode" } , { "-l" , MCX_OPT_HASARG | MCX_OPT_INFO , MY_OPT_LIST , NULL , "-l {all|zoem|legend|trace|builtin|session|filter|parmode} (list and exit)" } , { "-nsegment" , MCX_OPT_HASARG , MY_OPT_NSEGMENT , "" , "maximum segment depth" } , { "-nstack" , MCX_OPT_HASARG , MY_OPT_NSTACK , "" , "maximum stack depth" } , { "-bzoem" , MCX_OPT_HASARG | MCX_OPT_HIDDEN , MY_OPT_BZOEM , "" , "initial nrof zoem dictionary buckets" } , { "-buser" , MCX_OPT_HASARG | MCX_OPT_HIDDEN , MY_OPT_BUSER , "" , "initial nrof user dictionary buckets" } , { "-nuser" , MCX_OPT_HASARG , MY_OPT_NUSER , "" , "size of user dictionary stack" } , { "-nenv" , MCX_OPT_HASARG , MY_OPT_NENV , "" , "size of environment dictionary stack" } , { "--err-out" , MCX_OPT_DEFAULT , MY_OPT_ERR_OUT , NULL , "redirect verbosity/error output to stdout" } , { "--stress-write" , MCX_OPT_DEFAULT , MY_OPT_STRESS_WRITE , NULL , "for stress-testing zoem via write#3 (testing only)" } , { "-allow" , MCX_OPT_HASARG , MY_OPT_ALLOW , "[:]*" , "program invocations to allow (by name only)" } , { "--unsafe" , MCX_OPT_DEFAULT , MY_OPT_UNSAFE , NULL , "allow system calls, prompt for confirmation" } , { "--unsafe-silent" , MCX_OPT_DEFAULT , MY_OPT_UNSAFE_SILENT , NULL , "allow system calls silently" } , { "--system-honor" , MCX_OPT_DEFAULT , MY_OPT_SYSTEM_HONOR , NULL , "require system calls to succeed" } , { "--split" , MCX_OPT_DEFAULT , MY_OPT_SPLIT , NULL , "prepare for split output" } , { "--readline-off" , MCX_OPT_DEFAULT , MY_OPT_NORL , NULL , "turn off readline in interactive mode" } , { "-amcs" , MCX_OPT_HASARG | MCX_OPT_HIDDEN , MY_OPT_AMCS , "" , "alloc maximum chunk size" } , { "-amic" , MCX_OPT_HASARG | MCX_OPT_HIDDEN , MY_OPT_AMIC , "" , "alloc maximum invocation count" } , { "-hf" , MCX_OPT_HASARG | MCX_OPT_HIDDEN , MY_OPT_HF , "
}\2\@{}} \def{ssion#1}{\iref{session}{\v{\\\1}}} \sec1{intro}{Introduction} \par{ \bf{Zoem:} The sound made by electrical devices and flying bugs. Pronounced: \it{zoom} or \it{zum}; the vowel is short. } \par{ Zoem is a general macro/programming language with filtering capabilities. It transforms text in two stages.} \par{ In the first stage the text is scanned for macro escape sequences. The core zoem language consists of so-called primitive macros. They provide a wide spectre of functional behaviour, including data storage, arithmetic evaluation, \io facilities, iteration and flow control, dictionary stacks, system interaction, and regular expressions. As with any macro/programming language, the real power comes from the ability to create new user-defined macros in terms of primitives and other user-defined macros. Macro expansion can be arbitrarily delayed, and inside-out evaluation is supported.} \par{ A useful feature is the combination of anonymous macros, lists, and the \pr{apply#2} primitive, constituting a kind of callback mechanism in zoem. Another feature is the automatic popping and pushing of dictionaries with the begin/end environment, providing shadowing and localization.} \par{ In the optional second stage, the text is filtered. Two filter scopes are distinguished. The first is called \it{device scope} and is always enclosed in a filter escape sequence. The second, \it{plain scope}, is everything else. Filtering mechanisms are provided for both. The filtering language is useful when the output is meant to be in an external format with device-specific escape sequences, such as \html or troff. Conversions are specified in device specific filtering rules that are applied in plain scope, so that the zoem input is device agnostic. By setting up different filtering rules the same input can be used to generate different outputs.} \par{ This manual covers the whole zoem language. A large part of it is only interesting for someone writing a reusable macro package. A smaller part is still interesting for someone who is just using such a package, but might want to add some utilities and shortcuts of his own. The part where file inclusion, macro definitions, and macro expansions are explained is required reading for anyone considering or planning to use zoem.} \sec2{}{Other documentation} \par{ \sibref{zoem}{The manual page of the zoem interpreter}. } \par{ Zoem is used by \aref{http://micans.org/pud}{Portable Unix Documentation} (\pud) and \aref{http://micans.org/aephea}{Aephea}. The latter is a general authoring tool for writing \html documents and provides both useful abstractions and a framework for creating new abstractions. It uses and promotes the use of \css. A small core of Aephea has been ported to the typesetting language \em{troff}. This core is used in \pud, which provides mini-languages for \faq documents and \unix manual pages. Documents written in \pud can be output to troff and html, and further to plain text, PostScript, and \pdf. } \sec2{click}{About this document} \par{ Clicking on the number next to a section title (e.g. the \ref{click}{num} to the right of the title \bf{About this document} of this section) will get you to the corresponding section of the table of contents. } \par{ Zoem input and zoem output are \it{both} generally shown in a typeface font, \v{like this}. } \par{ \enref{colours}{} Links that point to locations within this document are shown in \iref{colours}{blueish colors}. Links that point to documents originating from the same package (project) or perhaps the same site are shown in in \lref{zum.html}{greenish colors}. Links that point to other stations on the internet or perhaps other packages on the same site are shown in in \aref{http://www.google.com}{reddish colors}. } \sec1{toc}{Table of Contents} \"aephea::maketoc" \sec1{nutshell}{Zoem in a nutshell} \par{ Zoem supports several programming constructs, immediate and postponed expansions, stream character filtering, easy \io facilities, integer arithmetic, and a whole lot more. Its main aims are:} \begin{itemize}{ {flow}{compact} {interitem}{0} {align}{right} } \item \car{ Providing the building blocks for a structural and programmable approach. \iref{features}{Section \ref{features}{num}} contains an overview of the zoem primitives and their use.} \item \car{ Accepting a pleasant syntax that does not require much thinking, favouring simplicity and rigor over looseness and context dependent rules.} \item \car{ Creation from the keyboard while minimizing on key-strokes.} \item \car{ Few meta characters. Zoem achieves this by having a single special character and a reasonably restricted syntax.} \item \car{ Adding filtering capabilities so that multiple devices can be addressed.} \end{itemize} \sec2{features}{Expressive power (features)} \par{ Listed below are some features of the zoem primitives. In practice there are two kinds of zoem files. The first is a zoem macro file, which should contain macros defined in terms of lower-level macros, with zoem primitives at the lowest level. The second is a zoem document file, which should import such a macro file and only use the high-level macros defined in that macro file. Additionally, a document file can define some high-level macros of its own, in terms of low-level macros, zoem primitives, or a mixture of both. } \begin{itemize}{ {flow}{compact} {interitem}{0} {align}{right} } \item \car{ Macros with arguments, overloading of key names allowed (i.e. different keys with the same name are distinguished by the number of arguments they take). (\pr{def#2}, \pr{set#2}, and \pr{setx#2}). Zoem primitives look like regular macros, but usually they expand their arguments before use. User macros can be equipped with this behaviour by wrapping them in \pr{apply#2}.} \item \car{ Support for variable number of arguments - see the \iref{vararg}{vararg} section.} \item \car{ Easy file, \stdin, \stdout, and \stderr input/output, nested file inclusion (\pr{dofile#2}, \pr{write#3}, \pr{finsert#1}, and \pr{zinsert#1}).} \item \car{ Extensive support for arithmetic with the primitives \pr{let#1}, \pr{f#2}, \pr{f#3}, \pr{fv#2}, and \pr{eqt#3}.} \item \car{ Operators returning booleans (\pr{defined#2}, \pr{cmp#3}, \pr{eqt#3}), control operators acting on those (\pr{while#2}, \pr{if#3}).} \item \car{ The \it{for}-like primitives \pr{apply#2} and \pr{table#5}.} \item \car{ Match and substitution capabilities using \posix regexes (\pr{inspect#4}).} \item \car{ Register macros with \pr{register#2} to be processed after regular processing (e.g. to output counters or warnings).} \item \car{ The switch primitive \pr{switch#2}, employing the \iref{vararg}{vararg construct}.} \item \car{ Localized expansions (\pr{eval#1}) and meta-zoem (\pr{!} and \pr{!#1}).} \item \car{ A user dictionary stack that can be manipulated using \pr{push#1} and \pr{pop#1}. An environment environment for doing \mc{begin{stuff}} \v{..} \mc{end{stuff}} stuff (see \pr{env#4}). This environment creates name scopes by pushing and popping to/from the \iref{dictionary}{dollar dictionary stack}. Environments may take arguments, one particular useful application is that local variables (e.g. local to an \it{itemize} environment) can thus be specified by the user.} \item \car{ Storage of data by multiple string indexing \- arbitrary data can be stored in a tree by indexing nodes with (arbitrary) strings. Refer to the \secref{grape} section.} \item \car{ The ability to nicely format macros (see \pr{formatted#1}).} \item \car{ \iref{xmlsugar}{Syntactic sugar} for writing \sgml-style mark-up and having it checked.} \item \car{ Executing system commands, possibly sending data to \stdin and receiving data from \stdout \- \pr{system#3}.} \item \car{ And more.} \end{itemize} \sec1{cline}{Invoking zoem from the command line} \par{ You use zoem by invoking it from the command line. The normal mode of operation is that you specify a file for zoem to chew up and spit out. This is called the \it{entry file}, and its name usually has the extension \v{.azm}. A common invocation looks as follows:} \verbatim{zoem -i mcl.azm} \car{ The \v{-i} flag specifies the entry file. It is not necessary to write the \v{.azm} extension, zoem will append it for you. The preceding could also have been entered as} \verbatim{zoem -i mcl} \car{ In either case, zoem will set the session key \ssion{__fnbase__} to the base name of the entry file, i.e. the name stripped of its \v{.azm} suffix and any leading path components. In this example, the key \ssion{__fnbase__} will get the value \v{mcl}. If you have an input file without the \v{.azm} extension, you need to use the \v{-I} option.} \par{ Zoem writes its output to a default output file which is named according to three rules. The rules are:} \begin{itemize}{ {flow}{compact} {interitem}{0} {align}{right} } \item \car{ If the \v{-o} flag was given the value say \v{somestr}, zoem will write to the file named \v{somestr}.} \item \car{ If \v{-o} was not supplied but the \v{-d} flag was used with argument say \v{zyx}, zoem will write to the file named \ssion{__fnbase__.zyx}. The -d flag also results in the macro \ssion{__device__} being set to \v{xyz}.} \item \car{ If neither \v{-d} nor \v{-o} was given, zoem will write to the file named \ssion{__fnbase__.ozm}.} \end{itemize} \par{ It is possible to change the default output file from within the document; this is achieved with the \pr{writeto#1} primitive. Zoem can mingle default output with output to other files, use the \pr{write#3} primitive for that.} \par{ Both the \v{-i} and \v{-o} flag accept a hyphen as argument, meaning respectively that zoem will read from \stdin and write to \stdout.} \par{ Specifying just zoem and entering a return will cause zoem to enter interactive mode, in which it reads from \stdin and writes to \stdout. Interactive mode currently should catch any errors occurring, so it is a good way of experimenting and testing. By default, interactive mode reads chunks that are ended by a single dot on a line by itself. This behaviour can be changed by setting the session variable \ssion{__parmode__} using the \v{-s} option. Using \v{zoem -l parmode} shows the bits that can be set in this variable. It is for example possible to make zoem read paragraphs (ended by two or more consecutive newlines).} \cpar{Note}{ There is a difference between specifying \it{no} output stream (i.e. not using the \v{-o} option) and explicitly specifying \v{-o -}. In the latter case, zoem will never enter interactive mode. Should you need to insert zoem into some pipe sequence, then you need to use \v{-o -}.} \cpar{Tracing errors}{ If your document contains erroneous input (e.g. using a macro that was never defined), zoem will by default print the approximate corresponding line number of the current input file and the last key it saw, and then exit. If that does not suffice in tracking down the error, you have a choice of options. One possibility is to use one of the various tracing modes described below and in the zoem interpreter manual. Another possibility is to specify the \v{-x} option which says to enter interactive mode should an error occur. This enables you to inspect the values of keys defined or used in the problematic area. A selection of other options is given below. For the full story, consult \sibref{zoem}{the manual page of the zoem interpreter}.} \: mq \begin{itemize}{ {flow}{cascade} {interitem}{1} } \item{\v{-h}} \car{ lists all flags accepted by zoem with a short description for each.} \item{\v{-s =}} \car{ Sets key \mc{foo} to \v{bar}.} \item{\v{-e }} \car{ Zoem will evaluate \v{}, writing any result text to \stdout, and then exit.} \item{\v{-E }} \car{ Zoem will evaluate \v{}, writing any result text to \stdout, and then proceed.} \item{\v{-x}} \car{ If an error occurs, zoem stops processing and enters interactive mode.} \item{\v{-l }} \car{ lists all entities specified by \v{}. It can be any of \v{all}, \v{filter}, \v{legend}, \v{alias}, \v{session}, \v{trace}, or \v{zoem}. Repeated use is allowed. In fact, zoem will only check whether the target is present as a substring, so} \verbatim{zoem -l legendzoem} \car{ will print the legend and the list of zoem primitives. } \item{\v{--trace}} \car{ This traces (prints) all keys encountered, and prints possibly truncated arguments. Zoem has several other tracing flags, use the \v{-h} flag or refer to the zoem manual page for more information.} \par{ Tracing can be set from within the document using the \pr{trace#1} primitive. Part or whole of the data tree can be output from within the document using the \mc{%dump} primitive (refer to the \secref{grape} section).} \item{\v{--stats}} \car{ When zoem is done, it prints statistics about the primitive name table and about the user name table.} \end{itemize} \sec1{syntax}{Zoem syntax and parsing} \sec2{nomenclature}{Syntax and nomenclature} \par{ Zoem parses text which may contain zoem \bf{escape sequences}, these are sequences that have special meaning and cause zoem to do special processing. Each and every escape sequences starts with a backslash, no exceptions. There are three kinds of sequences that are \it{macros}, which may or may not take arguments. These are zoem primitives, user keys, and dollar keys.} \par{ There are currently about sixty zoem primitives, these are listed in the \capref{language} section. Sixty is quite a lot; it includes convenience sibling sets such as \pr{set#2}, \pr{setx#2}, \pr{def#2}, and \pr{def#2}, and entries covering a variety of areas such as \io, arithmetic, testing, control, string conversions, formatting, shadowing (scopes), and all the other stuff listed in the \secref{topicindex} section.} \par{ Additionally there are a number of zoem built-ins that are defined in terms of primitives. Built-ins live in the same dictionary as primitives and behave the same in all aspects. The next section has some further remarks on the differences and resemblances between primitives/built-ins on the one hand and user macros on the other hand.} \par{ User keys and dollar keys are discussed in the \capref{macro} section. Arguments are shipped by delimiting them with curly braces, as in} \verbatim{\mc{thiskey{takes}{\\bf{two}\\it{arguments}}}.} \car{ No characters are allowed inbetween (the delimiting curlies of) two arguments (but take note of the handy \pr{formatted#1} primitive). See the \capref{macro} section for more information. Zoem is very strict in the syntax it accepts, but it \it{garantuees} to accept a text in which each backslash \mc{} is escaped as \mc{\\} (i.e. a text in which all consecutive runs of backslashes have even length).} \par{ An \bf{active backslash} is any backslash that is not made inactive by an active backslash immediately preceding it. The first backslash seen by zoem (proceeding sequentially through the text) is active. This is one incomprehensible way of stating the obvious, and I bet you know what I mean anyway. An active backslash must always have a meaning known to zoem. If zoem does not get it, it will complain and exit. The meaning (i.e. class) of the escape sequence introduced by an active backslash is determined by the character immediately following it. A list is given below.} \par{ Within arguments, curlies not functioning as argument delimiters must also be escaped if they are not balanced. It is best practice to escape all non-argument-delimiting curlies, but I never do so myself unless they are not balanced. An \bf{escaped curly} is a curly preceded by an active backslash. An \bf{active curly} is a curly that is not escaped. A pair of \bf{balanced curlies} consists of an active left curly that matches an active right curly, where inbetween all escaped curlies are disregarded. A \bf{block} is anything delimited by balanced curlies. The word \bf{scope} is most often used to distinguish between \bf{device scope} and \bf{plain scope}, these are the two kinds of \bf{parse scopes}. An \bf{environment scope} refers to the stuff enclosed by instances of the \pr{begin#2} and \pr{end#1} primitives. So called \bf{name scopes} are entered and exited by \pr{push#1} and \pr{pop#1}.} \: \par \: A macro invocation is started with an active backslash, followed by an \: admissible macro name. This can be either a zoem primitive, or a \: user defined macro. The next section defines which names are \: admissible. This macro invocation (the active backslash followed \: by the macro name) can be followed by one or more blocks. \sec2{namespaces}{Primitives, built-ins and user macros} \par{ Zoem distinguishes between primitives and built-ins and user macros on the other hand. Consider the following slightly contrived example.} \verbatim{\protect{\:{/} \def{fib#1}{ \push{fibonacci} \set{a}{1} \set{b}{1} \set{c}{0} \while{\let{\a <= \1}}{ \setx{c}{\a} \setx{a}{\let{\a + \b}} \write{-}{txt}{\c\|} \setx{b}{\c} } \pop{fibonacci} }}} \car{ The example is contrived in that zoem is not the most appropriate language to compute Fibonacci numbers. The reason for using it is that extracts from existing macro packages require more context and are simply more boring.} \par{ In the example, the following macros are primitives: \bf{\pr{push#1}}, \bf{\pr{pop#1}}, \bf{\pr{def#2}}, \bf{\pr{set#2}}, \bf{\pr{while#2}}, \bf{\pr{let#1}}, \bf{\pr{setx#2}}, and \bf{\pr{write#3}}. The example defines a user macro \bf{\v{\\fib#1}}, which can be invoked e.g. as \v{\\fib{100}}. Doing this either from a file or from interactive mode should give the output below.} \verbatim{1 2 3 5 8 13 21 34 55 89} \par{ From the above it can be seen that a macro (primitive or user-defined) is in this text often referenced by its signature. The signature contains both the name of the macro and the number of arguments it takes, separated by the \v{#} (octothorpe) character. The octothorpe and ensuing integer are omitted if a macro does not take arguments. A new macro is defined by specifying the required signature (without the leading backslash) as the first argument of one of the definition macros. In this text a signature is usually prefixed with the backslash.} \par{ The example above also defines user macros \v{a}, \v{b}, and \v{c}. The \pr{set#2} primitive will not warn when a previous definition exists. The \pr{setx#2} acts similarly but will also first evaluate the value assigned to the macro. Finally, \pr{push#1} and \pr{pop#1} temporarily create a new dictionary in which the definitions are stored. This is one easy way to ensure that no other definitions are overwritten. This level of care is generally not required though.} \par{ The following are useful to know about primitives, built-ins and user macros.} \begin{itemize}{{align}{right}{flow}{compact}{mark}{\@{•}}} \item \car{ Primitives and built-ins live in one namespace (or dictionary), user macros live in another.} \item \car{ A built-in is a special macro provided by zoem. It is defined in terms of one or more primitives, but its definition lives in the same dictionary as primitives do. It is called a built-in because its definition is built into the zoem interpreter. Example: \v{begin#1} is defined as \v{\\begin{\\1}{}} (cf \pr{begin#2}). The full list can be obtained by issuing \v{zoem -l alias}.} \item \car{ Primitives and built-ins can be shadowed by user-macros, but a warning will be issued. You can test this by issuing e.g. \v{\\def{def#2}{\\set{\\1}{\\2}}}. This particular piece of code redefines \pr{def#2} as \pr{set#2} by shadowing the primitive \mc{def#2} as a user macro, losing the property of \pr{def#2} that it warns if a key already exists.} \item \car{ Primitives and built-ins can \it{always} be accessed by prefixing the name with a right quote, as in \v{\\'def{foo}{bar}}. The prefixed primitive syntax also has the advantage that it is slightly faster, although zoem speed is likely not something one should worry about.} \item \car{ It is impossible to access a user macro with the quote prefix syntax.} \end{itemize} \par{ It is probably a good idea in macro packages that export functionality to use the primitive quote prefix syntax. This protects the package from user redefinitions. At the same time, the ability to shadow zoem primitives implies that user macros (also those exported by macro packages themselves) are protected against potential clashes with zoem primitives that may be introduced in later versions of the language. The Fibonacci example looks as follows using the quote prefix syntax.} \verbatim{\protect{\:{/} \'def{fib#1}{ \'push{fibonacci} \'set{a}{1} \'set{b}{1} \'set{c}{0} \'while{\'let{\a <= \1}}{ \'setx{c}{\a} \'setx{a}{\'let{\a + \b}} \'write{-}{txt}{\c\|} \'setx{b}{\c} } \'pop{fibonacci} }}} \par{ The quote mechanism only works for zoem primitives and built-ins that follow the syntax of user macros. This includes names starting with a dollar \v{$} or with a double quote \v{"}. The primitive \pr{$#2} and the built-ins \v{\\""} and \v{\\""#1} are the only examples in this category. The quote mechanism does not work for special zoem primitives such as data keys (\secref{grape}), delay keys (\pr{!#1}), or \xml syntactic sugar (\secref{xmlsugar}).} \sec2{escape}{List of escape sequence classes} \par{ This is a list of escape sequence classes recognized by zoem, indexed by the (set of) character(s) triggering the class(es) \- this assumes that the character in question is preceded by an active backslash.} \begin{itemize}{ {flow}{cascade} {interitem}{1} } \item{\v{$[_a-zA-Z]*}} \car{ [dollar key] A sequence starting with a dollar sign possibly continued with underscores and alphanumeric characters. Introduces a dollar key. No dollar signs are allowed in the remainder, and the first non-alphanumeric non-underscore character terminates the sequence. The primary use of dollar keys is that they are set by \pr{begin#2} and \pr{end#1}. Dollar keys live in the dollar dictionary stack, which is pushed and popped by \pr{begin#2} and \pr{end#1}. Nested \v{begin/end} scopes can thus safely associate different values with the same key name. Refer also to the \capref{macro} section, the \capref{language} section, and the \capref{dictionary} section.} \par{ Note: \pr{$#2} is the only zoem primitive starting with a dollar.} \item{\v{[_a-zA-Z][_a-zA-Z0-9]*}} \car{ [user key/zoem primitive] A sequence starting with an underscore or an alphabetic character, with only underscores and alphanumeric characters in the remainder. Introduces a user key or a zoem primitive. The first non-alphanumeric non-underscore character terminates the sequence. These keys live in the \it{user dictionary stack}, which the user can control with the \pr{push#1} and \pr{pop#1} primitives. Refer also to the \capref{macro}, \capref{language}, and \capref{dictionary} sections.} \par{ A sequence consisting of a single underscore (i.e. not followed by an alphanumeric character) introduces an \iref{anonymous}{anonymous key}.} \item{\v{"}} \car{ [user key or zoem built-in] Starts a user key, which is only different from the user keys mentioned above in that it looks different. The sequence is terminated by a closing\~\v{"}. Inbetween, anything is allowed except a backslash or curly. This is used for creating mnemonic names such as } \verbatim{\ \\"man::author" \\"man::section" \\"man::version" \\"html::title" \\"html::charset"} \car{ These keys live in the \it{user dictionary stack}. See the \capref{macro} section and the \capref{dictionary} section.} \par{ There are two zoem built-ins that take this particular form. These are \mc{""} and \mc{""#1}. Both expand to nothing. The first can be used to temporarily separate two pieces of text, as they will be joined after expansion. The second can be used to quickly outcomment sections of text.} \item{\v{'}} \car{ [primitive quote prefix] As seen above, primitives and user keys largely live in the same syntactic namespace. It is possible to unambiguously invoke a primitive by inserting a right quote to the left of the primitive key or built-in. Refer to section \secref{namespaces}.} \par{ The user keys live in a stack of dictionaries. Dictionaries can be pushed and popped using \pr{push#1} and \pr{pop#1}. The default user dictionary is always present and acts as a global namespace. It is possible to retrieve a key \mc{foo} directly from the global namespace using the syntax \mc{''foo}, even if it is shadowed in stacked dictionaries. It is possible to set a key in the global namespace using \pr{set#3}. } \item{\v{%}} \car{ [data key] A sequence starting with a percent sign. The percent sign is followed by a number of scopes. This is used to access multi-dimensional data storage. Such data is stored using the \pr{def#2} primitive or one of its siblings. Refer also to section\~\secref{grape}.} \item{\v{[1-9]}} \car{ [positional parameter] A single (character encoding a) positive digit. The sequence backslash followed by digit is called a \it{positional parameter}. It is only interpreted in the second argument of \pr{set#2}, \pr{setx#2}, \pr{def#2}, and \pr{defx#2}, and in the definition part of an \iref{anonymous}{anonymous key} (which can be an argument to \pr{apply#2} and \pr{inspect#4}). In all these instances, the sequence denotes a positional parameter into which the corresponding argument will be interpolated when a key with arguments is used. It is allowed in other places though, as it is possible in zoem to create key definitions dynamically (see e.g. the \pr{setx#2} primitive). \bf{Note} during interpolation, positional parameters that are enclosed by the \it{delay scope} \v{\\!{..}} will not be interpolated (see \pr{!#1}). The status of this feature is not entirely clear.} \item{\v{}} \car{ [strip newline] The newline will be stripped during the interpretation stage. If you want the newline to be stripped during the file-read preprocessing stage use the sequence \v{\\:{/}}, which is a special case of the comment sequence (see below).} \item{\v{:}} \car{ [preprocessing sequence] There are a few preprocessing sequences, which are evaluated during file read (cf the \capref{fileread} section). The most important preprocessing sequence is simply the sequence \mc{:} followed by whitespace, an alphanumeric character, or a backslash. It introduces a comment up till and excluding the next newline, which is stripped.} \item{\v{|}} \car{ [zoem glyph] Comprises a special two-character sequence that can be given a device-specific meaning. It is customarily used to encode a line break. To zoem, this sequence is more or less the same as a 'normal' character. See the \pr{special#1} primitive.} \item{\v{~}} \car{ [zoem glyph] It is customarily used to encode a non-breaking space. See the entry above.} \item{\v{-}} \car{ [zoem glyph] It is customarily used to encode a long dash. See two entries back.} \item{\mc{}} \car{ [backslash] Denotes a literal backslash.} \item{\v{\{}} \car{ [left curly] Denotes a literal left curly.} \item{\v{\}}} \car{ [right curly] Denotes a literal right curly.} \item{\v{*}} \car{ [glyph sequence] Starts a glyph sequence or constant sequence. Refer to the \capref{dscope} section and to the \pr{constant#1} primitive.} \item{\v{<}} \car{ [syntactic sugar] This introduces syntactic sugar for directly writing \sgml-style mark-up, such as \html and \xml (e.g. DocBook). Refer to the \iref{xmlsugar}{anchor section} for that topic.} \item{\v{@}} \car{ [at scope] \it{Typically seen in macro package files only}. Starts a special instance of device scope called \it{at scope}. The sequence\~\mc{@} \it{must} immediately be followed by a pair of balanced curlies, so at scope always appears as \mc{@{..}}. Refer to the \capref{dichotomy} and \capref{dscope} sections for more information.} \item{\v{&}} \car{ [and scope] \it{Typically seen in macro package files only}. May only be used within device scope, and implements a limited form of macro expansion within that scope. The sequence\~\mc{&} \it{must} immediately be followed by a pair of balanced curlies. so and scope always appears as \mc{&{..}}. Refer to the \capref{dichotomy} and \capref{dscope} sections for more information.} \item{\v{`}} \car{ [back quote - formatting escape] \it{Typically seen in macro package files only}. Must be followed by a pair of balanced curlies enclosing a formatting sequence. This is only recognized within the \pr{formatted#1} primitive. This primitive removes all literal whitespace it encounters in its argument; the formatting sequences are transformed to the whitespace characters encoded by them.} \item{\v{,}} \car{ [comma - atomic separator] \it{Typically seen in macro package files only}. This is interpreted during filter time, and is always mapped to nothing. Use it for glueing things as in \mc{foo\\,1}, which will result in \v{theresultoffoo1}.} \item{\v{!}} \car{ [delay sequence] \it{Typically seen in macro package files only}. Introduces a zoem meta sequence. Such a sequence consists of a maximal run of consecutive backslashes, possibly followed by a single block. It can be used to delay interpretation during any number of interpretation stages, and is useful to delay interpretation, perhaps even in a nested fashion, for arguments in keys such as \pr{apply#2} that expand one or more of their arguments before use. The run of exclamation marks (or 'bangs' as they are internally called) actually comprises an argument to the underlying primitive, so the two primitives (one taking a single block argument) internally have respective signatures \v{!#1} and \v{!#2}. Externally though, they are just refered to as \pr{!} and \pr{!#1}.} \item{\v{=}} \car{ [inline files] \it{Rarely used feature}. Starts either a sequence of the form \mc{={fname}}, which begins a so called inline file named \v{fname}, or a sequence of the form \mc{==}, which ends such an inline file. Refer to the \capref{fileread} section.} \end{itemize} \par{ This leaves \v{0>()[]?^#/.;} for future use, hopefully very few of these will ever acquire meaning. If the sequence\~\mc{#} acquires meaning, it will probably be for encoding Unicode scalar values.} \sec2{stages}{Parsing stages} \par{ Parsing is separated into three stages, conceptually. Zoem knows two different parse scopes, plain scope and device scope. These are mentioned below, and explained in the \secref{dichotomy} section. The three stages are:} \begin{itemize}{ {flow}{compact} {interitem}{0} {align}{right} } \item File read \item Macro expansion / file inclusion - only plain scope is seen. \item Filtering - both plain scope and device scope are filtered. Device directives that lay hidden in device scope are interpreted during output. \end{itemize} \par{ A file is read in chunks, if possible. The requirement is that chunks must end on lines and be in the outermost scope. The default minimum chunk size is approximately one megabyte. Chunks are processed by recursively chunking them into smaller chunks as dictated by macro expansion. As soon as a chunk is no longer subject to macro expansion it is immediately filtered and output.} \par{ Macro expansion is done recursively. Whenever a macro is encountered, it is replaced by its expansion, and the result is again fed to the parser. Evaluatation is not necessarily lazy, that is, during macro expansion the expander may expand arguments before they are interpolated and substituted in the macro definition. This inside-out evaluation can recurse if necessary. Many zoem primitives evaluate one or more of their arguments before use. The default behaviour for user macros is lazy evaluation. This can be changed however by wrapping both the macro and its arguments in \pr{apply#2}. Expansion can be delayed using \pr{!} and \pr{!#1}, so different arguments can be treated differently.} \par{ Important is that the result from the second stage is still valid zoem input. If you re-feed it to zoem, file read and macro expansion are usually no-ops (unless some interpretation delay-magic was used), and the syntax is garantueed to be acceptable to zoem. This is because device scope is not touched during the first two stages, and device specific text (which is most likely not conforming to zoem syntax) lies always hidden in that scope. There are three kinds of escape sequences introducing device scope; these are described in the \secref{dscope} section.} \par{ This is used for example when creating a table of contents; you can write expanded but unfiltered content to a file and read it in during the following run. It is important that such content is fully expanded, because you want things like index numbers and references as they are at the time of macro invocation. It is equally important that what you read back in is still valid zoem input; this is simply achieved by witholding filtering. When the table of contents is read in, it can be subjected to filtering, and this is the right way to do toc stuff in Zoem.} \sec2{fileread}{File read} \par{ File read - stripping comments, reading inline files.} \par{ Zoem searches for files included via \pr{dofile#2} or one of its built-in aliases in a number of places if it cannot find the file in the current directory. The precise way of searching is documented in section \secref{searchpath}.} \begin{itemize}{ {flow}{compact} {interitem}{1} } \item{\mc{:}} \car{ In most cases, this sequence introduces a comment, namely where it is followed by whitespace, an alphanumeric character, or a backslash. It introduces a comment up until and excluding the next newline, which is stripped.} \par{ The sequence \v{\\:{/}} introduces a comment up till and including the newline. This feature can be useful within the \pr{protect#1} primitive, as it is the only way to delete actual newlines within the argument of that primitive.} \par{ The sequence \v{\\:{!}} is replaced by a backslash. The single use currently known is to make it easy to quote zoem input containing comment sequences. This} \verbatim{\\protect{\\foo \\bar \\zut \:{!}\:{!}: this will end up as a comment. }} \car{ will result in the following} \verbatim{\\foo \\bar \\zut \:{!}\: this will end up as a comment.} \set{{dict}{itemize}}{$flow}{cascade} \item{\mc{={fname}}} \car{ starts inline file named fname at the next line, removes remainder of line after the \mc{={fname}} sequence. When using the \pr{dofile#2} primitive or one of its four built-in aliases, an inline file takes precedence over regular files in the file system, whether it is present (as a regular file) or not. See below. This feature can be used to ship zoem input in one piece while putting the macro parts at the end. \pr{zinsert#1} can address inline files as well, but \pr{finsert#1} cannot. The reason for this is that inline files have to satisfy zoem syntax, whereas \pr{finsert#1} can be used to read arbitrary data.} \par{ The future will probably bring a zoem option that creates such a self-contained file automatically from the zoem entry file.} \set{{dict}{itemize}}{$flow}{compact} \item{\mc{==}} \car{ ends inline file, removes remainder of line.} \end{itemize} \par{ The above applies to any file read at any stage. Inline files may occur in any file included at any time, but they do not nest.} \par{ The \it{zoem entry file} is the single file that is specified on the command line. This is the main file, from which other files can be included if desired.} \par{ Zoem entry files usually have the extension \v{.azm}, which is memnonic for \bf{A ZoeM} file. This is required if the \v{-i} option is used. Arbitrary entry file names can be specified using the \v{-I} option. It is not uncommon to generate sibling files with \v{.roff}, \v{.html}, \v{.zmt} (zoem table of contents), and \v{.zmr} (zoem references) extensions \- however, this is all configurable in user space and not part of zoem itself. There are no restrictions on names of files that are included from the entry file. Inclusion is done recursively.} \par{ The future will probably bring a second extension that is allowed, namely \v{.ezm} for \bf{Expanded ZoeM} file, which is a self-contained file in which every included file is present as an inline file.} \sec2{searchpath}{File search path} \par{ If zoem cannot find a file in the current directory, it attempts to find the file in one of three different ways. These are, in the order in which they are attempted:} \begin{itemize}{{align}{right}{flow}{compact}} \item \car{ The environment variable \v{$ZOEMSEARCHPATH} is checked. It may contain a listing of paths separated by whitespace or colons.} \item \car{ The zoem variable \ssion{__searchpath__} is checked. It must contain a listing of paths stored as a vararg, i.e. a sequence of paths where each path is delimited by curly brackets. \bf{DO NOT} overwrite this variable, but rather append or prepend to it. Most likely zoem was configured and compiled locally on your system, in which case \ssion{__searchpath__} contains the path necessary to find the macro packages \v{man.zmm}, \v{faq.zmm}, and \v{ref.zmm}.} \item \car{ The path of the file currently being parsed is used. Assume that file \v{foo} contains \mc{import{/a/b/c/bar}}. If file \v{bar} wants to include file \v{zut}, which is in the same \v{/a/b/c/} directory, it need not prepend a path but can just issue \mc{import{zut}}. Should the previous search mechanisms fail to find zut, then zoem will as a last resort deduce the path from \v{/a/b/c/bar}. This feature is probably rarely needed, if ever at all.} \end{itemize} \sec2{macro}{Macro expansion} \par{ Macro expansion consists of recursive file inclusion and macro expansion. All zoem primitives and user keys are recursively expanded until none remains. Zoem primitives and user keys take one of the following forms:} \begin{itemize}{ {flow}{cascade} {interitem}{1} } \item{\mc{abc_0123_}} \car{ A key with alphanumerics and underscores only. Ends with any other character. All zoem primitives but one have this form.} \par{ Note: \mc{_} denotes an anonymous key, see the \capref{anonymous} section.} \par{ These keys live in the \it{user} dictionary stack. Initially, there is only one dictionary. The stack can be manipulated using the \pr{push#1} and \pr{pop#1} primitives.} \item{\mc{"abc::def-ghi.jkl,mno+qrs"}} \car{ A quoted key. Almost anything inbetween quotes is allowed. Always ends with a quote. No zoem primitive has this form. These keys live in the same \it{user} dictionary stack as the keys above.} \item{\mc{$abc_0123_}} \car{ A key introduced with a dollar sign. The name may further consist of alphanumerics and underscores and it ends with any other character. These keys live in the \it{dollar} dictionary stack. A dictionary is pushed with every occurrence of \pr{begin#2}, and that dictionary is popped with the corresponding occurrence of \pr{end#1}.} \par{ Further note: \pr{$#2} is a zoem primitive.} \end{itemize} \par{ All three types of keys may take arguments, and overloading is allowed:} \verbatim{\ \\foo \\: signature foo \\foo{bar} \\: signature foo#1 \\foo{bar}{bop} \\: signature foo#2 \\$foo{bar}{baz} \\: signature $foo#2 \\"foo::oof"{zut}{zit}{zot} \\: signature "foo::oof"#3} \car{ is an ensemble of valid and unique keys, which can be defined for example by} \verbatim{\ \\def{foo}{FOO} \\def{foo#1}{The FOO of \\1} \\def{foo#2}{The FOO of \\1 and \\2} \\def{$foo#2}{The $FOO of \\1 and \\2} \\def{"foo::oof"#3}{\\foo{\\1}{\\2}\\foo{\\2}{\\3}}} \car{ Additionally, zoem allows the definition of \it{constant keys} that map directly into device space and are ignored during macro expansion. Usage of such keys looks like \mc{*{'e}} or \mc{*{(c)}} and is detailed later on.} \par{ A sequence\~\mc{k} where k is in 1-9 is allowed within anonymous keys (as used for example in \pr{apply#2} and \pr{inspect#4}) and in the definition argument of the \pr{def#2} primitive and its siblings \pr{defx#2}, \pr{set#2}, and \pr{setx#2}. It indicates the position(s) where arguments should be interpolated. \bf{Note} during interpolation, positional parameters that are enclosed by the \it{delay scope} \v{\\!{..}} will not be interpolated (see \pr{!#1}). The status of this feature is not entirely clear.} \par{ A feature that should only rarely be needed is that zoem allows name scopes. Refer to the \capref{dictionary} section.} \sec2{}{File inclusion} \par{ There is one zoem primitive which has four different uses. For each of those uses, a built-in alias exists.} \verbatim{\ \\dofile#2 use alias meaning \\dofile{expr}{!+} \\input{expr} require file, interpret and output \\dofile{expr}{!-} \\import{expr} require file, interpret only \\dofile{expr}{?+} \\read{expr} permit absence, interpret and output \\dofile{expr}{?-} \\load{expr} permit absence, interpret only} \car{ The \pr{dofile#2} primitive and its four aliases are perhaps a little funny interface-wise \- better ideas are welcome. The \v{expr} argument is \it{digested}, that is, expanded until no macro's remain. It is thus possible to specify \ssion{__fnbase__.zmt} and include a table of contents file that has been written to in a previous run. \pr{dofile#2} and its aliases have the property that zoem really descends into the files, and on error will emit a message containing the approximate line number where it occurred.} \par{ Additionally, the contents of a file can be placed inline using \pr{finsert#1} and \pr{zinsert#1}.} \par{ Note: wherever \v{key} is written, it means that something of the form \mc{foo}, \mc{$foo}, or \mc{"foo"} has to be provided, so you would use \pr{setx#2} e.g. as \mc{setx{foo}{\\finsert{\\__fnbase__.zyx}}}.} \sec2{protection}{Protection} \par{ The \pr{dofile#2} primitive requires that the files to be included satisfy zoem syntax. It will descend into the files and proceed parsing them.} \par{ The \pr{finsert#1} and \pr{zinsert#1} primitives do not descend, but rather act as if the contents of the file specified were pasted into the place of macro invocation.} \par{ \pr{finsert#1} will \it{protect} the contents of the inserted file, that is, all backslashes and curlies are escaped by preprending them with a backslash. \pr{zinsert#1} will include the file unchanged, assuming that its contents satisfy zoem syntax.} \par{ The \pr{system#3} primitive is able to pipe data to a system command's \stdin stream and retrieve data from the command's \stdout stream. This primitive will \it{unprotect} the data it sends, and it will protect the data it receives. \bf{Note} the security implications of this feature as discussed at the \pr{system#3} entry.} \par{ Data can be explicitly protected using the \pr{protect#1} primitive.} \par{ Protected data can (currently) never result in it being expanded again. This is because escaped backslashes are only interpreted at filter time, and never during expansion. If you only need \it{temporary} delay of expansion, use the \pr{!} primitive or the \pr{!#1} primitive.} \sec2{dichotomy}{Scope dichotomy} \par{ Zoem knows two parse scopes: \bf{plain scope} and \bf{device scope}. The latter is also called 'at scope' because \mc{@{..}} is one (but not the only) way of entering device scope. In plain scope, every character represents itself as a glyph, i.e. as something that should show that way in print/on screen (after the zoem output/device input is fed to the device interpreter).} \par{ For example, if you write the less than sign\~\v{<} in plain scope, it should show up as a readable less than glyph, like in this very sentence. In order to make this happen, zoem provides the \pr{special#1} primitive, so that the less than sign can be automatically mapped to the html entity sequence \v{<}.} \par{ In device scope, nothing is mapped except for a double backslash should it occur. If you enter this particular sequence of mixed scope: \mc{@{}\\@{}} as zoem input, the zoem output/device input is (provided the \pr{special#1} primitive was correctly used for the html device): \v{<hello world>} and what you finally see on screen is: \@{}\@{}. In device scope, every character (except for the escape sequences available in that scope) represents itself as the character that should be present in the zoem output/device input. Device scope should normally only be seen in macros and not in running zoem input.} \par{ In plain space you type characters just as you want to see them eventually \- when you read the document after the zoem output was run through a device interpreter (such as a browser or printer, or postscript previewer). The only exceptions are the backslash and the two curlies, these should be entered as\~\mc{\}}, \mc{\{}, and\~\mc{\}}, respectively. Those escape sequences are interpreted as the characters or glyphs \mc{}, \v{\{}, and\~\v{\}}. For all characters, including these three, it is checked whether they should be further mapped according to the \pr{special#1} primitive. If a mapping is found, it is retrieved and interpreted by the device scope filter. Read on.} \sec2{dscope}{Device scope} \par{ There are three kind of strings which are interpreted by the generic device filter, and which are said to live in device scope:} \begin{itemize}{ {flow}{compact} {interitem}{0} {align}{right} } \item \car{ The strings embedded in \mc{@{..}} sequences.\|} \item \car{ The strings mapped to by the \pr{special#1} primitive, including mappings of the zoem glyphs\~\mc{~}, \mc{|}, and\~\mc{-}.} \item \car{ The strings mapped to by the \pr{constant#1} primitive.} \end{itemize} \par{ In a macro package that is meant to work for multiple devices, every use of any of these constructs will typically be embedded in something that tests the value of the active device. This can be done using either \pr{cmp#3} with \pr{if#3}, \pr{switch#1}, or \pr{$#2}, in conjuction with the pre-defined zoem key \ssion{__device__}, containing the name of the active device (which can be specified on the command-line). The following are equivalent:} \verbatim{\ \\if{\\cmp{eq}{\\__device__}{html}}{ \\@{} }{} \\: is equivalent with \\${html}{ \\@{} }} \car{ The \pr{$#2} primitive is used if something needs to be done for one device only, and it may occasionally appear in documents. For example, the \aref{http://micans.org/pud/}{\pud} man macros enable the creation of a table of contents (for both html and troff). My own convention is to have a table of contents only in html, and I specify this using the sequence} \verbatim{\mc{${html}{\\"man::maketoc"}}} \car{ When zoem enters device scope, it outputs all characters literally, except that the backslash still has special meaning. It is used for encoding the backlash itself (as \mc{\\}), and for encoding the two curlies\~\v{\{} and\~\v{\}} (as \mc{\{} and\~\mc{\}}). This is the same as in plain scope (except that in plain scope the resulting character may again be mapped onto something else, for example, in troff the backslash also needs encoding as \mc{\\}).} \par{ In device scope the sequence\~\mc{"} maps to a double quote. This is an additional feature to allow zoem input to be more susceptible to some editors moving features. It is not \it{necessary} though; simply using the double quote without escaping it is sufficient.} \par{ Additionally, the backslash can be followed by a single letter from a prescribed set listed below. Such a backslash+letter combination is called a \it{device directive}. By default, zoem will never print consecutive newlines, and it will never print consecutive spaces or spaces at the beginning of a line. The device directives allow this to be altered.} \begin{itemize}{ {flow}{compact} {interitem}{0} } \item{N} \car{garantuee a newline} \item{P} \car{garantuee a paragraph skip (two consecutive newlines)} \item{S} \car{garantuee a space (except if next char is newline)} \item{I} \car{increase indent by one (indent is printed after each newline)} \item{J} \car{decrease indent by one} \item{C} \car{set indent to zero} \item{n} \car{print newline} \item{s} \car{print space} \item{t} \car{print tab} \item{w} \car{stop managing white space (squashing spaces and newlines)} \item{W} \car{start managing white space (use after\~\v{w})} \item{&} \car{start \it{and} scope (see further below)} \item{+} \car{set the special level (see further below)} \end{itemize} \par{ Note that the directives mainly affect the lay-out of the device text (which is zoem output), not the look of the interpreted device text. The '\v{N}' directive is rather important when constructing troff macros, as many special troff commands are encoded by a dot as the first character on a line, i.e. a newline followed by a dot. Since troff attaches special meaning to two consecutive newlines as well (interpreting it as a paragraph break), zoem needs to be able to specify \it{print a newline only if the previous character was not a newline}. This is exactly what the \v{N}\~directive means. The '\v{W}' and '\v{w}' directives are required for enabling the construction of a verbatim environment.} \par{ The sequence \mc{&{}} can be used to avoid overly cumbersome constructions. It is for example illegal to write} \verbatim{\protect{\@{}}} \car{ In the early days of zoem, you had to write} \verbatim{\protect{\@{
}}} \car{ \- ugly by most standards. Today you write} \verbatim{\protect{\@{
}}} \car{ Which is not any shorter, but more pleasant to read. What happens is that the contents of \it{and} scope \v{\\&{..}} is first fully expanded in plain scope, after which the result is passed back to device scope. You have to be careful though. The content of \v{\\&{..}} should never expand to something containing the \it{at} sequence \v{\\@{..}}, because device scope is not allowed to nest. It should also not expand to something containing the \it{and} sequence \v{\\&{..}} either, as this sequence is illegal in plain scope.} \sec3{special}{Device scope resulting from mapping special characters} \par{ The first kind of zoem escape introducing device scope is \mc{@{..}}. The second kind comprises the \pr{special#1} mappings, including the three zoem glyphs\~\mc{~}, \mc{|}, and\~\mc{-}. Conventionally, these are used to encode a non-breaking space (\v{ } in html), a line break (\v{
} in html), and a long dash (emdash, not present in html). You would for example put} \verbatim{\ \\if{\\cmp{eq}{\\__device__}{html}}{ \\special{ {38} {&} \\: 38 is ascii character '&' {60} {<} \\: 60 -> '<' {62} {>} \\: 62 -> '>' {-1} { } \\: the zoem escape \\~ {-2} {
\\!N} \\: the zoem escape \\| {-3} {-} \\: the zoem escape \\- } }{ }\ } \car{ All \pr{special#1} definitions are interpreted in device scope. For every character encountered in plain scope, it is checked whether a \pr{special#1} definition exists, if so, the corresponding string is retrieved and this is filtered through the device scope filter. Note that the three zoem glyphs described here may not be used in device scope, they can only be used in plain scope. In device scope you will have to write the explicit, device-specific sequence such as \v{
} (in html).} \par{ The \pr{special#1} primitive allows different levels of mappings to be defined simultaneously. Several definitions of the same character are allowed; these are placed on a stack particular to that character (cf. the \pr{special#1} entry). When zoem encounters a character for which one or more mappings exist, it retrieves a mapping using the \it{special level}. This is an integer that has by default the value\~\v{1}. Each open output stream has a unique special level associated with it. [Output streams exist for the \it{default output file} (see e.g. \pr{writeto#1}) and for each file openend by \pr{write#3}]. A mapping is retrieved using this rule: \it{The deepest element is fetched for which the depth does not exceed the level}. The most visible element (which is the element first occurring in the \pr{special#1} invocation) has depth\~\v{1}.} \par{ The presence of different levels comes in handy e.g. when the troff device is used. In some contexts, the double quote is a special character in troff (and a printable quote is then mysteriously represented by \it{two consecutive double quotes}), in most contexts it is not. This is combatted by including these two specifications in the \mc{special#1} call preparing for troff output (note that 34 is the \ascii value representing the double quote):} \verbatim{\\special{ ... {34}{"} {34}{""} {92}{\\\\e} ... }} \car{ The first pair shown simply maps the double quote onto itself, and the second pair maps it onto a double double quote. As long as the special level is\~\v{1}, the second definition is not used. The backslash (with \ascii value \v{92}) needs only one definition as it is escaped in the same way in all troff contexts.} \par{ The special level can be set using the \mc{+}\~directive, which must be followed immediately by a digit in the range \v{0-9} enclosed by curly brackets, e.g. \v{\\@{\\+{2}}} will set the special level to \v{2}. The special level \it{can} be set to\~\v{0} (zero) and this means that no character will be mapped.} \cpar{Example}{ Double quotes need to be escaped in certain troff contexts. This is achieved by the following.} \verbatim{\\@{\\+{2}"} ... funny quote context ... \\@{"\\+{1}}} \car{ Such a context is typically encapsulated by a macro defined in a package; its definition should never be visibile to the user of the package. Note that the double quotes embedded in \it{at} scope in the example above are not susceptible to special mapping \- mapping is only applied in plain scope.} \sec3{glyph}{Device scope resulting from glyph definitions} \par{ The third kind of device scope strings are those mapped to by the \pr{constant#1} primitive. An example of (toy) usage is this:} \verbatim{\ \\constant{ {'e} {é} \\: Use e.g. as \\*{'e}l\\*{`e}ve (\*{'e}l\*{`e}ve) {(c)} {©} \\: Use e.g. as \\*{(c)} DEEDEE (\*{(c)} DEEDEE) {+-} {±} \\: Use e.g. as \\*{+-} a few (\*{+-} a few) }} \car{ This is largely convenient syntactic sugar. These constants could also have been defined as} \verbatim{\ \\def{"'e"}{\\@{é}} \\def{"(c)"}{\\@{©}} \\def{"+-"}{\\@{±}}} \car{ The idea is that the \mc{*{..}} namespace is used for glyph-like device-specific bindings, whereas the \mc{".."} namespace is used for semantic purposes that are device-independent, but nothing prohibits you from fiddling with this.} \sec2{xmlsugar}{\sgml/\html/\xml syntactic sugar cubes} \par{ Zoem provides a shorthand for entering \sgml-style tags. It is checked by zoem for well-formedness of the resulting \sgml code, and it can be freely mixed with other modes of entering tags. Normally you would have to enter \sgml-style tags in device scope, or write a macro for doing that. For example, a macro \v{x#2} that expands \mc{x{b}{be bold}} to \mc{@{}be bold\\@{}} is a likely candidate. However, this would be inelegant for constructions that span a long distance, and it does not provide for letting zoem expressions expand within an xml tag.} \par{ Zoem provides the \mc{<} token. It can be used in several ways:} \verbatim{\protect{ \ \:{!}: foo can be an expression. Some \:{!}: of course, expressions may occur here as well. over here. \{zut} \:{!}: bar can be an expression too; \:{!}: this syntax will close itself. Some \:{!}: again, expressions may occur here as well. over there. \<> \:{!}: this is a closing tag for the first foo. \ works too. \ \:{!}: zoem knows this closes itself. \<*br> \:{!}: zoem converts this to
}} \car{ Suppose that foo, bar, and zut are zoem expressions expanding to strings FOO, BAR, and ZUT respectively (FOO and BAR might be of the form \v{tag a="b" c="d"}). Provided that the characters\~\v{<}, \v{>}, and\~\v{&} are automatically mapped in plain scope (as a result of correct \pr{special#1} usage), the above will result in} \verbatim{\ Some <content> over here. ZUT Some <content> over there.
} \car{ The \v{foo} part inside the \mc{} syntax should never expand to something containing a\~\v{>}. This is entirely the responsibility of the user or macro package author.} \par{ Both kinds of syntax, \mc{} and \mc{{zut}}, are kept as they are during the expansion stage, and they can be subjected to multiple levels of expansion (which may be the case if such syntax is used inside e.g. \pr{setx#2} or \pr{apply#2}). It is only at the output stage that the syntax is transformed to actual \sgml code and that well-formedness is checked. So, the two examples just seen will first transform to \mc{} and \mc{{ZUT}} (please note that foo, bar, and zut all denote expressions here). If they are at that point no longer subject to expansion they enter the output stage where they are converted to \v{} and \v{ZUT} (plus some additional formatting/indenting) respectively.} \par{ Zoem pushes on a stack of opening tags whenever it encounters \mc{} syntax during the output stage. It naturally knows that a tag can be followed by attributes. It also knows that a tag such as \mc{} closes itself (\xml syntax), and the applies for \dtd tags such as \mc{}. As a special case, \mc{<*tag foo bar zut>} is converted to \v{} to allow encoding of \html tags such as \v{}, \v{}, and \v{
}. This syntax is mandatory for tags that will not be closed. Note that you should only use \mc{

} if you are going to use \mc{

} or \mc{<>} as well (because zoem requires closing tags for opening tags). That said, the syntax \mc{

{ paragraph content }} is preferable in most cases. } \par{ Zoem does not know about other ways of entering tags, so \mc{@{}} would not affect the stack just mentioned. \mc{<>} automatically closes the top level opening tag from the stack. Again, syntax such as \mc{@{}} does not interact with the stack. } \par{ It is possible to explicitly close a tag by simply using \mc{} syntax. Zoem will check whether the closing tag matches the top level opening tag. As seen before, \mc{<>} does the same thing, but rather than doing a check, zoem will use the top level opening tag to construct the corresponding closing tag.} \sec1{}{Zoem miscellanea} \sec2{signature}{Key signatures} \par{ Several keys take another key as argument, e.g. they store a value in a second key or check whether the second key exists. The full list of these meta keys is \pr{def#2}, \pr{defx#2}, \pr{set#2}, \pr{setx#2}, \pr{undef#1}, \pr{defined#2}, \pr{apply#2}, and \pr{inspect#4}. In all cases, the argument key is passed as the first argument, by means of the \bf{key signature}.} \par{ For a key \mc{key} taking \v{k}\~(\v{k}>0) arguments its signature is \v{key#k}. The signature of a key \mc{key} taking no arguments is simply \v{key}. The rule is: Key usage always includes a single leading backslash (this activates the key). When a key is subject of inspection, it is always referred to by its signature.} \par{ Throughout this text, a key with signature \v{key#k} is mentioned by means of its \bf{key mention} \mc{key#k}, that is, for extra clarity the backslash is prepended to the signature.} \par{ As explained in \capref{namespaces}, almost all primitives can be specified using quote syntax. The quote syntax is integrated with signatures. This means that primitives that expect a signature (such as \pr{def#2}, \pr{undef#1}, and \pr{apply#2}) accept quoted signatures too when the signature refers to a primitive.} \sec2{anonymous}{Anonymous keys} \par{ A single underscore introduces an \bf{anonymous key}. It is optionally followed by a \v{#k} tag (for\~\v{k} in\~\v{1..9}), denoting the number of arguments the anonymous key takes. An occurrence of the latter is called a \bf{tagged anonymous key}. The first argument to the key should be a key definition, the other arguments are the arguments for that key definition. If a tag is present, it is used for verifying that the anonymous key is used properly.} \: hierverder: this used to be useful because: \: This feature may be helpful when an anonymous key is the result of \: expanding the first argument to \pr{meta#3}. \: and now? -- the example below does not work with \!: \: \begin{vbt} \: \\def{foo}{#2{\\1 the \\2}} \: \\def{bar}{#3{\\1 the \\2 and \\3}} \: \: \\meta{_\\foo}{x}{{billy}{kid}} \: \\meta{_\\bar}{x}{{william}{fourth}{maxima}} \: \\meta{_\\bar}{x}{{william}{fourth}} \: \end{vbt} \: \: results in \: \: \begin{vbt} \: billy the kid \: william the fourth and maxima \: \end{vbt} \: \: and the third will fail. \verbatim{\ \\_{\\1 the \\2}{row}{boat} \\_#2{\\1 the \\2}{row}{boat}} \car{ results in} \verbatim{\ row the boat row the boat} \car{ Anonymous keys may occur in the first argument of \pr{apply#2}, within the first argument of \pr{inspect#4}, and they may occur freely in running text. The presence of a tag is required when an anonymous key is used within either of \pr{apply#2} and \pr{inspect#4}. An example of usage in \pr{apply#2}:} \verbatim{\ \\apply{_#2{\\1 kisses \\2\\|}}{{bill}{max}{max}{bill}} bill kisses max max kisses bill} \car{ or even} \verbatim{\ \\set{%foo}{{{\\1 hugs \\2\\|}}} \\apply{_#2\\%{foo}}{{bill}{max}{max}{bill}} bill hugs max max hugs bill} \car{ Note that in order to store a block with \pr{set#2}, an extra pair of curlies has to be used, as blocks can only be passed as a sub-argument of a single-element \iref{vararg}{vararg}. Also note that in a vararg it is allowed to put white space inbetween the constituting elements.} \sec2{grape}{Tree data} \par{ Data can be organized in a global tree with a specialized use of \pr{set#2} and its siblings, as shown further below. The data is retrieved from the tree using so called data keys. Such a key is started using a percent sign, immediately followed by zero, one, or more blocks, e.g. \mc{%}, \mc{%{..}}, and \mc{%{...}{...}{...}} would all be allowable invocations. If more than one block follows the percent sign, there must be no interleaving white space.} \par{ The underlying primitive has signature \v{%#1}, as the trailing scopes are congregated into a single argument before they are further processed. The two sibling primitives \v{%free#1} and \v{%dump#1} serve for freeing and dumping parts or whole of the tree, as described further below.} \par{ When applied to data keys, \pr{set#2} and its siblings set one or more values in a global multi-dimensional associative array that we shall refer to here as \v{ROOT}. Please note that \v{ROOT} is for explanatory purposes only. This associative array is best viewed as a tree, in which every node can have branches to higher nodes. A node may or may not contain a value. Let us denote the value contained by a node \v{some-node} as \v{*(some-node)}. The fact that \v{beta} is a node one branch higher than \v{alpha}, which is in turn one branch higher than \v{ROOT}, is denoted as \v{ROOT->"alpha"->"beta"}. In this \it{path} notation, strings indexing nodes in the trees are written inbetween quotes. This has the advantage that the empty string, which is a valid index string, has the representation \v{""}. Combining these conventions, we write the value associated with \v{beta} as \v{*(ROOT->"alpha"->"beta")}. Consider these examples.} \verbatim{\ \\set{%{foo}{bar}{zut}}{lez} \\: now *(ROOT->"foo"->"bar"->"zut") is "lez" \\set{%{foo}{bar}{zut}}{{a}{b}{x}{y}} \\: now *(ROOT->"foo"->"bar"->"zut"->"a") is "b" \\: and *(ROOT->"foo"->"bar"->"zut"->"x") is "y" \\: and *(ROOT->"foo"->"bar"->"zut") still is "lez" \\: some special cases \\set{%{foo}{bar}{zut}}{{{c}}} \\: now *(ROOT->"foo"->"bar"->"zut") is "{c}" \\set{%{foo}{bar}{zut}}{{c}} \\: now *(ROOT->"foo"->"bar"->"zut") is "c" \\set{%{foo}{bar}{zut}}{c} \\: now *(ROOT->"foo"->"bar"->"zut") is "c" \\set{{foo}{bar}{zut}}{{c}{d}{e}} \\: This does nothing, because the second argument \\: must either be an *even* vararg, a 1-element vararg, \\: or a simple argument. \\set{%{{tiger}}}{in the woods} \\: now *(ROOT->"{tiger}") is "in the woods" \\set{%{tiger}}{in the woods} \\: now *(ROOT->"tiger") is "in the woods" \\set{%tiger}{on the loose} \\: now *(ROOT->"tiger") is "on the loose" \\: stripping curlies from a vararg with one argument \\: does not make a difference with the exception of \\: the case shown below. \\set{%{}}{empty} \\: now *(ROOT->"") is "empty". \\set{%}{root} \\: now *(ROOT) is "root".} \car{ Take note of the rule governing the second argument. If the first non-white space character is a left curly, \pr{set#2} expects a vararg. The vararg must either be even or it must contain exactly \it{one} argument.} \par{ An even vararg is interpreted as a sequence of key-value pairs. Each key induces a new branch from the node specified in the first argument, and each value is associated with the node at the end of that branch. If the vararg contains exactly one argument, that argument is simply used as a value. This is the only way to specify a block as the value. If the first non-white space character is not a curly, \mc{set#2} will simply interpret the second argument as a value to append to the node specified in the first argument. It is possible to sidestep these issues by using \pr{set#3} and the directive \v{u} as argument to the \v{modes} key. This will cause the value to be copied without further interpretation as a vararg or block. } \par{ If you want the data to be stored to be expanded before it is bound, use \pr{setx#2} or \pr{defx#2}.} \par{ Data is retrieved simply by prefixing the path with the \mc{%} token. Example:} \verbatim{\ \\set{%{foo}{bar}{zut}}{{a}{b}{x}{y}} \\%{foo}{bar}{zut}{a} \\%{foo}{bar}{zut}{x}} \car{ will print \v{b} and \v{y}. If the path is not an existing path in the current tree it will simply be ignored, although an error message will be emitted.} \par{ Whole or part of the data tree can be freed using the \mc{%free} primitive. Again, simply append the access sequence in which you are interested. For freeing the entire tree, use \mc{%free} without trailing scopes. The \mc{%free} primitive largely exists for testing purposes to ensure that zoem gets its internal data manipulation right.} \par{ Whole or part of the data tree can be output for debugging purposes using the \mc{%dump} primitive. Simply append the access sequence in which you are interested. For printing the entire tree, use \mc{%dump} without trailing scopes. This can be used for debugging if your data manipulation does not work out as expected. There is no result text as far as usual processing is concerned. The underlying primitive dumps its findings to \stdout in a line-based textual representation of the data-tree.} \sec2{vararg}{Of blocks and varargs} \par{ A \bf{block} is a string beginning with a left curly and ending with a right curly, the curlies being balanced. This is a convenient naming convention. Blocks can be used in constructing anonymous keys; refer to the \capref{anonymous} section.} \par{ Some keys take a \it{vararg} argument, which is a single argument (enclosed by curlies as are all arguments), which can contain any number of sub-arguments, that is, a list consisting of blocks. Inbetween the blocks white space may occur. The \pr{special#1} and \pr{constant#1} keys both take a single vararg argument, and the \pr{apply#2} and \pr{switch#2} keys each take a vararg as their second argument. For \pr{apply#2} the first argument is a key that is applied to subsequent batches of arguments from that vararg. The \pr{table#5} primitive takes a vararg as its last argument. For examples, see the \capref{tour} section and the \pr{apply#2} entry.} \par{ An \bf{even vararg} is a vararg with an even number of elements, An \bf{odd vararg} is a vararg with an odd number of elements.} \par{ User keys may check whether an argument is a vararg by employing the \pr{nargs#1} primitve. This can be used to take different actions depending on the structure of the argument.} \sec2{session}{Session keys} \car{ This is a compact listing of session keys, created by issuing \v{zoem -l session}.} \verbatim{\system{../src/zoem}{{-l}{session}}} \car{ This manual is littered with examples of the usage of \ssion{__device__}. The \ssion{__fnbase__} key is useful for creating sibling files of the entry file, i.e. a table of contents file or a file containing reference information. I have the habit of naming those \ssion{__fnbase__.zmt} and \ssion{__fnbase__.zmr}, respectively. The \ssion{__fnin__} key is useful for emitting log, warning, or error messages particular to the file currently being parsed. The \ssion{__parmode__} macro affects the way in which zoem reads chunks in interactive mode (refer to Section\~\secref{cline}). The \ssion{__searchpath__} macro is one of the ways in which zoem can be instructed to search for files in a set of locations, when confronted with \pr{dofile#2} or one of its built-in aliases. Section\~\secref{searchpath} has more information about the mechanism of file location. See also \sibref{zoem}{session}{the zoem manual}.} \sec2{builtin}{Built-in macros} \par{ This is the result from doing \v{zoem -l builtin}:} \verbatim{\system{../src/zoem}{{-l}{builtin}}} \sec2{dictionary}{Dictionary stacks} \par{ By default, when using \pr{def#2} and \pr{set#2}, keys and their values are put in a global user dictionary. It could be useful to shadow keys by entering a new name scope. Zoem facilitates this by providing the \pr{push#1} and \pr{pop#1} keys. These push and pop a new dictionary onto/from the user dictionary stack.} \par{ A second dictionary stack is the \it{dollar dictionary stack}, which contains all keys that start with a dollar sign. The \pr{begin#2} primitive pushes a dollar dictionary each time it is invoked, and that dictionary is popped by the corresponding \pr{end#1} invocation. This is typically useful for creating nested environments that need access to the same type of information - by storing such information in dollar keys, it can be shadowed and recovered. Refer to the \pr{begin#2} entry.} \par{ When a key is used its definition is searched in all dictionaries, starting from the top-level dictionary. The key \pr{undef#1} has only access to the top-level dictionary, and will never delete a key in any other dictionary.} \sec1{tour}{A zoem tour} \par{ What follows is an informal tour through zoem's offerings. The next section contains a comprehensive overview of the zoem primitives.} \par{ Let us start with how filtering in plain space is configured. The following was obtained from the \aref{http://micans.org/pud/}{\pud} man macros.} \verbatim{\ \\switch{\\__device__}{ {html}{ \\special{ {38} {&} {60} {<} {62} {>} {-1} { } \\: the zoem escape \\~ {-2} {
\\!N} \\: the zoem escape \\| {-3} {-} \\: the zoem escape \\- } } {roff}{ \\special{ {46} {\\\\.} {96} {\\\\`} {92} {\\\\\\\\} \\: a single backslash {-1} {\\\\ } \\: the zoem escape \\~ {-2} {\\!N.br\\!N} \\: the zoem escape \\| {-3} {\\\\-} \\: the zoem escape \\- } } {\\write{stderr}{txt}{No such device: \\__device__\\|} \\write{\\__fnbase__.err}{txt}{No such device: \\__device__\\|} \\exit } }\ } \car{ Take note of the number of backslashes. In order to print a backslash in troff, the troff input must contain two consecutive backslashes. In order to specify a backslash in zoem, we must also provide two, thus we need four backslashes in all (in order to create this example I needed eight backslashes in the zoem input).} \par{ Also note the use of the \pr{switch#2} primitive, which takes an expression in the first argument and an arbitrary number of pairs plus an optional clause in the second argument. The optional clause was in this case used as a failure test.} \par{ \pr{special#1} is an example of a zoem key taking an argument that may contain arbitrarily many sub-arguments (i.e. a \iref{vararg}{vararg}). In this particular case the sub-arguments must be paired, each pair defining how certain characters that are special to the device must be represented.} \par{ The \pr{write#3} and \pr{exit} need little comment, they work as expected. Zoem opens output files as needed, and closes them when it is done. The file name \v{-}\~is equivalent to either \stdout or \stdin (depending on context), the file name \v{stderr} denotes \stderr.} \: The \pr{dofile#2} input primitive and its aliases \: \pr{input#1}, \pr{import#1}, \pr{read#1}, and \pr{load#1} (you \: may abhor if you wish) \par{ \pr{exit} is considered a failure (and will cause zoem to stop and complain), but \mc{throw{done}} is not. \pr{throw#2} with argument \v{done} will merely quit parsing the current stack, so if you specify it at top level in a file \- not nested in a key that does its own parsing such as \pr{setx#2}, zoem will stop parsing the current file and transfer control back to the file from which it was included.} \par{ The previous example introduces the keys \ssion{__device__} and \ssion{__fnbase__}. They are so called session variables described in section \capref{session}.} \par{ A sibling primitive to \pr{special#1} is \pr{constant#1}. The following is an example of use.} \verbatim{\ \\constant{ {'e} {é} \\: Use e.g. as \\*{'e}l\\*{`e}ve (\*{'e}l\*{`e}ve) {(c)} {©} \\: Use e.g. as \\*{(c)} DEEDEE (\*{(c)} DEEDEE) {+-} {±} \\: Use e.g. as \\*{+-} a few (\*{+-} a few) }\ } \car{ The main thing to note here is that the target string (e.g. \v{é}) is \it{always interpreted in device space}. In the reference string (e.g. \v{'e}, \v{(c)} and \v{+-} in the example above) almost anything is allowed, including backslash-escaped characters and balanced curlies. The latter are not recommended though. } \par{ There are three zoem tokens representing the characters that have meaning to zoem syntax, the backslash and the two curlies. Those zoem tokens are just like any other plain characters: they can be mapped in plain space, and they are printed literally in device space.} \verbatim{\ \\\\ \\: A backslash; possibly mapped in plain space. \\{ \\: A curly; possibly mapped in plain space. \\} \\: A curly; possibly mapped in plain space. \\, \\: The atomic separator (vanishes).} \car{ These tokens are mapped only during the (final) filter stage. The atomic separator can be useful when you want to glue together items some of which will be the result of macro expansion.} \verbatim{\ \\def{foo}{bar} \\foo\\,1 \\: \\foo1 would be the key \\foo1} \car{ This will result in bar1. The tokens\~\mc{\\}, \mc{\{}, and\~\mc{\}} are really the corresponding ordinary characters. They can be mapped in plain space via \pr{special#1} using their \ascii values 92, 123, and 125 as was seen above for the backslash. In device space, they will result in\~\mc{}, \v{\{}, and\~\v{\}}.} \par{ Let us now continue with device scope by implementing a \mc{bf#1} key. Below you find two possible definitions:} \verbatim{\ \\def{bf}{1}{\\@{} \\1 \\@{}} \\: OK \\def{bf}{1}{\\@{ \\1 }} \\: Wrong! Wrong!} \car{ The second is wrong because the contents of\~\mc{1} end up in device space. If the expansion of\~\mc{1} still contains keys they will not be expanded (and cause a fatal syntax error when device space is filtered), and additionally any special characters in\~\mc{1} will not be mapped.} \sec1{language}{The zoem language} \sec2{}{Alphabetic index} \: this stuff constructs a 'Paragraph Of Contents'. \${roff}{\write{stderr}{txt}{no support for roff device!}\exit} \def{zzarg#1}{\{<\1>\}} \formatted{ \: third arg is a vararg in which all arguments of a key are stuffed. \def{zprim#3} { \setx{keyname}{\if{\defined{data}{{strangers}{\1}}}{\%{strangers}{\1}}{\1}} \setx{keyref}{\if{\cmp{eq}{\2}{0}}{\keyname}{\keyname\""_\2}} \setx{keysig}{\if{\cmp{eq}{\2}{0}}{\mc{\1}}{\mc{\1#\2}}} \setx{keycall}{\if{\cmp{eq}{\2}{0}}{}{:\~\~\mc{\1\apply{zzarg#1}{\3}}}} \@{\N\N} \@{\N\N} \keysig\keycall \write{\__fnbase__.prm}{copy} {\@{\N\N} \keysig \@{\N\N}\`{n} } } } \read{\__fnbase__.prm} \sec2{topicindex}{Topic index} \par{ This is an overlapping categorization in topics. } \begin{itemize}{ {flow}{cascade} {interitem}{1} } \item{\bf{Using and inspecting keys}} \pr{apply#2} \pr{constant#1} \pr{def#2} \pr{defined#2} \pr{defx#2} \pr{inspect#4} \pr{pop#1} \pr{push#1} \pr{set#2} \pr{setx#2} \pr{table#5} \pr{undef#1} \par{ These primitives affect or use either \it{user keys} that are stored in the user dictionary, \it{dollar keys} that are stored in the dollar dictionary, or \it{anonymous keys}. Dictionaries are discussed in \iref{dictionary}{Section\~\ref{dictionary}{num}}. } \item{\bf{Control, booleans, testing and comparison}} \pr{$#2} \pr{apply#2} \pr{branch#1} \pr{cmp#3} \pr{defined#2} \pr{dowhile#2} \pr{eqt#3} \pr{if#3} \pr{length#1} \pr{register#2} \pr{switch#2} \pr{undef#1} \pr{while#2} \item{\bf{Expansion, delay}} \pr{!} \pr{!#1} \pr{apply#2} \pr{defx#2} \pr{eval#1} \pr{setx#2} \item{\bf{Meta-zoem, introspection, exceptions, errors}} \pr{catch#2} \pr{exit} \pr{throw#2} \pr{try#1} \item{\bf{Execution, tracing}} \pr{trace#1} \item{\bf{Input/output}} \pr{dofile#2} \pr{finsert#1} \pr{format#1} \pr{register#2} \pr{vanish#1} \pr{write#3} \pr{writeto#1} \pr{zinsert#1} \item{\bf{Filtering}} \pr{special#1} \pr{vanish#1} \item{\bf{Environment scopes}} \pr{begin#2} \pr{end#1} \pr{env#4} \item{\bf{Name scopes}} \pr{pop#1} \pr{push#1} \item{\bf{Data storage}} \mc{%}, \mc{%free}, and \mc{%dump} are primitives described elsewhere \- refer to the \secref{grape} section. \item{\bf{String conversions}} \pr{format#2} \pr{inspect#4} \pr{length#1} \pr{textmap#2} \pr{tr#4} \item{\bf{Arithmetic}} \pr{f#2} \pr{f#3} \pr{fv#2} \pr{let#3} \item{\bf{Glyphs}} \pr{constant#1} \item{\bf{Syntactic sugar}} \pr{formatted#1} \pr{vanish#1} \xmlpr1ref \xmlpr2ref \end{itemize} \sec2{}{Primitives} \par{ Zoem primitives may expand (which is the same as evaluate) one, several, or all of their arguments before using them. Such arguments are enclosed by double angle brackets in the listing below. The inside-out type evaluation is done recursively and works for arbitrary levels of nesting. An argument which is first expanded and is then interpreted as a label is thus written \zarg{label} in the primary entry. In the definition text accompanying the entry, the expanded argument is simply refered to as \zarg{label}, so the extra pair of brackets is dropped. } \par{ Each primitive below has a little paragraph with the caption \bf{Result text}. It gives a summary of 'what comes out'. Note that the result of macro expansion is always passed to the parser again, so the result text is again subject to expansion. } \begin{itemize}{ {flow}{cascade} {interitem}{1} } \items{ {\enref{xmlpr1}{\mc{<>#1}}} {\enref{xmlpr2}{\mc{<>#2}}} } These are special. Refer to section \capref{xmlsugar}. The angle brackets are part of the syntax, do not confuse them with the angle brackets used below to enclose arguments. These primitives are respectively used as \mc{<*any*>} and \mc{<*any*>{*any*}}, so the positioning of arguments is different from all other zoem primitives. \item{\zprim{!}{0}{}} This primitive is triggered by an active backslash followed by a consecutive run of exclamation marks, which is \it{not} followed by an opening curly. The sequence is called a \it{delay sequence}, and its \it{arity} is the count of backslashes. A single exclamation mark is stripped (i.e. the arity is decremented) and the sequence is no longer subject to the current expansion stage. It is used to construct valid zoem input, which is usually redirected to file with the copy filter, stored using \pr{setx#2}, or used in nested occurrences of \pr{apply#2}, \pr{inspect#4}, and other primitives. Other uses are possible, the main thing is that one should keep a clear view of the meta-programming implied by\~\mc{!}. Refer also to the \pr{eval#1} primitive. \cpar{Example}{ The primitive \pr{eval#1} evaluates its argument a single time, and passes it on for further evaluation. The following are fully equivalent: } \verbatim{\protect{\set{foo}{zut} \eval{\!foo} \foo}} \car{ whereas \v{\\!foo} would pass the sequence \v{\\foo} to the filtering stage, where it will yield a (non-fatal) error message. Similarly, \v{\\eval{\\eval{\\!!foo}}} is equivalent to the above. } \cpar{Result text}{ A delay sequence of decremented arity. } \item{\zprim{!}{1}{{any}}} \car{ This primitive is triggered by an active backslash followed by a consecutive run of exclamation marks, which is in turn followed by a block. The block is called a \it{delay} scope. The arity of the delay scope is the count of backslashes found in the run. A single exclamation mark is stripped (i.e. the arity is decremented); if no further exclamation marks remain (i.e. the arity becomes zero) then the introducing backslash and the delimiting curlies are stripped as well. The result (including the contents of the block) is passed on and is no longer subject to the current expansion stage. The same observations hold as those made for the previous entry. Refer also to the \pr{eval#1} primitive. } \par{ Additionally, blocks that are protected by the delay primitive will be skipped during parameter interpolation. } \cpar{Result text}{ \zarg{any}, if the arity of the delay scope just found was equal to one, otherwise, \zarg{any} put in a decremented delay scope. \zarg{any} will in both case no longer be subject to the current expansion stage. } \item{\zprim{$}{2}{{str}{any}}} This is a shortcut for activating output for a particular device. If \ssion{__device__} expands to \zarg{str}, \zarg{any} is passed on for expansion, otherwise it is ignored. The following two are equivalent: \verbatim{\ \\${html}{Seen only in the html device} \\if{\\cmp{eq}{\\__device__}{html}}{Seen only in the html device}{}} \ccar{Result text}{ Either none or \zarg{any}. } \item{\zprim{apply}{2}{{}{}}} \car{ The first argument is expanded before use. It should expand either to the signature of a user key, primitive or builtin taking arguments, or to a \iref{anonymous}{tagged anonymous key}. Examples of the first are \v{foo#k} and \v{"bar::baz"#k}, the latter takes the form \v{_#k{..}}. If you use an anonymous key containing macro sequences, be sure to escape whole or part of the anonymous key, depending on your needs. The expansion of \v{_#2\\!{{}}} for example, will result in \v{_#2{}}. Primitives can used in both quoted and regular syntax.} \par{ The second argument should result in a vararg. \pr{apply#2} extracts \v{k}\~elements at a time from \zarg{vararg}, and applies the key resulting from the first argument to each vector of \v{k}\~elements successively. Any elements remaining in \zarg{vararg} are ignored.} \cpar{Result text}{ Entirely depending on the key specified in the first argument.} \item{\zprim{begin}{2}{{label}{}}} \car{ \pr{begin#2} pushes a new dictionary onto the dollar dictionary stack which is popped by the matching \pr{end#1}.} \par{ \mc{begin#1} is an alias which invokes \pr{begin#2} with an empty \zarg{vararg} argument.} \par{ \pr{begin#2} pushes the begin expression associated with \zarg{label} via \pr{env#4}. The \v{

} formatted blocks in html,
   while keeping the
   possibility to insert elements that do not take up any width (e.g. links).
   The first value block should contain the name of a macro.
   A likely candidate is
   \pr{length#1}, which should be specified simply as \v{length}.
   The first argument that is given to this macro will be the string
   under consideration.  The rest of the value blocks, if any, will be given
   as additional arguments.
   }

\par{
   Currently, this custom length computation is only applied to the
   argument that is being formatted and the two delimiters if present.
   All three of these can be replaced, for the purpose of length
   computation, by placeholders using the \it{double} directive.
   }

\item{\v{{double}{{[{key}{value}]*}}}}
\car{
   The directive is \v{double}, the value consists of a single block containing
   a vararg. This is used to specify placeholders when computing the length of
   elements.  The vararg contains placeholder types as keys and the
   corresponding placeholder values.  It is currently possible to specify three
   different types of placeholders. These are the argument to be typeset,
   specified with the placeholder key \it{arg}, the left delimiter, specified
   with \it{delimit-left}, and the right delimiter, specified with
   \it{delimit-right}.
   }

\cpar{NOTE}{
   The value is enclosed in a block, as part of the key-value specification
   employed by the \it{double} specification. The value itself is
   a block containing key-value pairs (again specified as curly-delimited
   blocks). So be sure to supply the correct number and nesting of blocks.
   }

\item{\v{{alignat}{{}{}}}}
\car{
   The directive is \v{alignat}, the value consists of two blocks.  This is used to
   specify alignment.  The content of the first value block is used as the
   string on which to align.  The content of the second block is used as the
   width on which the first part of \zarg{arg} (up to and including the
   alignment substring) will be right-aligned.  If the \v{length} specification
   is used as well, the length macro specified therein will be used to compute
   the width of the string specified in the first block.
   }

\item{\v{{reuse}{}}}
\car{
   This instructs zoem to reuse the current specification for another \zarg{num}
   arguments taken from \zarg{vararg}.
   Instead of \zarg{num} it is possible to specify \v{{reuse}{*}}. This
   will reuse the current specification until all arguments have been exhausted.
   }

\item{\v{{border}{{}{}}}}
\car{
   This borders the result of the current specification with \zarg{left}
   and \zarg{right}.
   This is useful in conjunction with the \v{reuse} specifier, for example
   for adding device line-breaks to each formatted item.
   }

\cpar{Example}{}

\verbatim{\protect{\:{/}
\format{%{{align}{right}{width}{10}{reuse}{*}{padding}{{'}{}}}}{
   {beauty}{lies}{in}{the}{eye}{of}{the}{beholder}
}}}
     
\car{results in}

\verbatim{\protect{\:{/}
''''beauty''''''lies''''''''in'''''''the'''''''eye''''''''of'''''''the''beholder}}

\end{itemize}


\cpar{Result text}{
   The formatted string.}


\item{\zprim{formatted}{1}{{any}}}
\car{
   This removes and adds white space from its arguments
   via the following rules:}

\begin{itemize}{
   {flow}{compact}
   {interitem}{0}
   {align}{right}
}
\item
\car{
   It skips any \mc{@{..}} enclosed sequence.}

\item
\car{
   It skips any \mc{<..>} enclosed sequence - note that the contents
   eventually will end up in \mc{@{..}} (at) scope.}

\item
\car{
   It removes all spaces, tabs, and newlines it encounters otherwise.}

\item
\car{
   It inspects and (after inspection) removes all \mc{`{..}} enclosed
   sequences it encounters.  During inspection, \pr{formatted#1} maps
   '\v{s}' to a space, '\v{t}' to a tab, and '\v{n}' to a newline.}

\item
\car{
   If the sequence \mc{`{<}} is encountered (not in at scope),
   \mc{formatted#1} starts copying literally without munging
   whitespace; it resumes its normal mode of operation
   after encountering the sequence \mc{`{>}}.}

\end{itemize}
   
\par{
 This is useful for writing legible macro files while exercising full control
 over whitespace (modulo Zoem's white space munging rules).}

\cpar{Result text}{
 The argument in its unformatted form.}


\item{\zprim{get}{2}{{dict-label}{key-sig}}}
\car{
   The user stack is searched from top to bottom for dictionaries
   with label \zarg{dict-label}, and those dictionaries
   are searched in order for a key with signature \zarg{key-sig}.
   The first succesful match is retrieved and its definition
   is pushed onto the interpretation stack.
   It is an error if no such definition is found.
   }

\cpar{Note}{
   The label of the default user dictionary is \v{''}. This ties
   in with the syntax \mc{''keysig}, used to specify the user
   dictionary stack. So the following:}

\verbatim{\protect{\:/
      \set{user}{Jill}
      \push{foo}
      \set{user}{Phil}
      \push{bar}
      \set{user}{Bill}
      \get{''}{user} \get{foo}{user} \get{bar}{user}}}

\car{
   yields output \v{Jill Phill Bill}.}

\cpar{Note}{
   It is currently not possible to access keys that take arguments.
   }


\cpar{Result text}{
   The result of processing the retrieved definition.}


\item{\zprim{if}{3}{{}{any1}{any2}}}
\car{
   The first argument is expanded and interpreted as an integer.
   If it is nonzero, \zarg{any1} is pushed on the interpretation stack
   and \zarg{any2} is ignored, vice versa if it is zero.}

\cpar{Result text}{
   Either \zarg{any1} or \zarg{any2}.}

\item{\zprim{inspect}{4}{{}{}{}{}}}
\ccar{status}{Experimental}

\par{
   All arguments are expanded before use. \zarg{vararg} currently
   recognizes a single key \it{mods}.  The value of \it{mods} may contain a
   comma-separated list of the following directives. Repeated use
   of \it{mods} is allowed.}

\verbatim{\:
   posix
   icase
   dotall
   iter-lines
   iter-args
   match-once
   discard-nmp
   discard-nil-out
   discard-miss
   count-matches}

\par{
   The \v{posix} directive is currently required, specifying that \posix
   regular expressions are used. The future might bring other regex syntaxes.}

\par{
   Argument \zarg{reg} specifies a (\posix) regular expression. Before being
   passed to the match engine, it undergoes \unix and \tilde tilde replacement
   as described in \sibref{zoem}{tildexp}{the zoem manual}.}

\par{
   Consult the \posix documentation or the regex(7) manual page for a description
   of posix regexp syntax.}

\par{
   The expansion of \zarg{any|anon key} can either result in plain data or in an
   anonymous key.  The expansion of the last argument results in data to which
   the regex \zarg{reg} is successively applied.}

\cpar{Interpolation}{
   If the second expansion starts with the pattern \v{_#k\{} it is assumed
   to be an anonymous key.  The subpatterns from the matched pattern are
   interpolated by the key, and the entire matched pattern is substituted by the
   interpolation.  Else, the matched pattern is simply replaced by the expansion.}

\par{
   \v{icase} induces case insensitive matching.
   \v{dotall} makes the dot\~\v{.} match any character, including the newline.
   \v{iter-lines} causes matching to be applied to lines shifted from the data (i.e.
     data is split on newlines).
   \v{iter-args} causes matching to be applied to blocks shifted from the data (which
     should obviously be a vararg).
   \v{match-once} inspects each element under consideration only once.
   \v{count-matches} replaces the data by the count of matches. In conjunction
     with \v{iter-lines} or \v{iter-args} it yields the counts on separate lines
     and in separate blocks, respectively.
   \v{discard-nmp} discards non-matching parts.
   \v{discard-miss} removes any lines or blocks which are empty after inspect
     is done with it.
   \v{discard-nil-out} discards any strings or lines or blocks that are empty
     after matching and optionally interpolation has been applied.}

\cpar{Bugs}{
   The \gnu implementation of \posix regexes was at some point known to be buggy
   for long strings and/or long matches.}

\par{
   A search pattern consisting of a single word boundary or the start-of-string
   token (\v{^}) will match at each position, because after a succesful match
   \pr{inspect#4} simply resumes searching for a new match by skipping to the
   end of the previous match (and adding a single position if the match had
   width zero and offset zero).  Similar but not yet noticed bugs may exist.}

\par{
   Nevertheless, this can be a very useful primitive for the occasional
   odd job, and it should always work except for the cases just mentioned.
   If you have a complicated instance of \pr{inspect#4}, test it first
   in isolation. Consider sending a bug report in case you find one (a bug,
   or a bug report).}

\cpar{Result text}{
   Depending on the presence of a match and the modifiers given.
   }


\item{\zprim{length}{1}{{}}}
\car{
   Computes the length of \zarg{any} and puts this in place.
   It takes into account the zoem escape sequences \mc{\\}, \mc{\{},
   and \mc{\}}. The future may bring a generalized \mc{length#2} primitive
   that provides different ways of measuring string length.}

\cpar{Result text}{The length of any \zarg{any}.}

\item{\zprim{let}{1}{{}}}
\car{
   The \pr{let#1} primitive puts zoem in arithmetic mode and the contents are
   parsed accordingly.  All of C's operators are supported  including the
   logical, bitwise, and comparison operators as well as the ternary operator.
   The operators \v{**} and \v{//} are added, which respectively denote
   exponentiation and integer division.
   Operations or functions resulting in integers are tracked, and
   the result will be stored in the integer type used (typically
   long) if possible. Thus one may find that}

\verbatim{\
\protect{\let{2**42}}
\protect{\let{2**22}}
}

\car{
   respectively result in \v{4398046511104.0} and \v{2097152}.}

\par{
   The precedence rules used by Zoem are simpler than C's. The respective groups
   of logical, bitwise, and comparison operators all have identical precedence
   internally, and associate from left to right.}

\par{
   Most of the \ansi C math functions are supported, with in addition
   \v{max} and \v{min}. The functions \v{round}, \v{sign}, and \v{abs} behave
   slightly different from their C counterparts, as they result in integer
   results if no overflow occurs.}

\par{
   At any place where an atomic type is expected one is allowed to insert
   a zoem macro invocation. It will be evaluated and the result will be
   interpreted as a number. Evaluation will take place in the order
   as dictated by the precedence rules governing the expression.}

\par{
   The logical operators shortcircuit and the ternary operator evaluates
   only one of its branches. This can be used to create side effects, such
   as in}

\verbatim{\protect{
   \let{\bar && \group{\set{foo}{zut}1}}
}}

\car{
   This sets \v{foo} only if \v{bar} evaluates to a non-zero number.
   The trailing\~\v{1} in the \v{group} macro is good practice because
   \pr{let#1} expects a number to be the result of any macro it encounters.
   It could have been any other number, or a macro or sequence of macros
   evaluating to a number.
   The \v{group} macro is a predefined macro that does nothing except
   passing its arguments. It is necessary in this concocted example
   because any occurrence of
   a macro within \pr{let#1} is interpreted as a number by itself.
   The sequence \v{\\bar \\bar} would for example be syntactically
   identical to \v{1 1}, which is incorrect.}


\cpar{Result text}{A number.}

\item{\zprim{nargs}{1}{{any}}}
\car{
   The argument is not expanded. It puts in place a number that indicates
   whether this argument could be parsed as a number of scopes or whether it is
   a regular argument. The following list of examples illustrates
   the rules according to which the number is created.}

\verbatim{\protect{
   \nargs{{abc}def}     : -2      \:{!}: neither fish nor fowl
   \nargs{abc}          : -1      \:{!}: regular argument
   \nargs{abc{def}}     : -1      \:{!}: regular argument too
   \nargs{}             :  0      \:{!}: empty vararg (not empty regular arg)
   \nargs{   }          :  0      \:{!}: empty vararg again
   \nargs{{abc}}        :  1      \:{!}: vararg with 1 argument
   \nargs{{abc}{def}}   :  2      \:{!}: vararg with 2 arguments
   \nargs{   {abc}
             {def}
   }                    :  2      \:{!}: vararg with 2 arguments
   \:{!}: etc.
}}

\par{
   From this it is seen that if the first non-whitespace character
   is an opening curly the primitive expects to find a number of scopes
   with nothing inbetween or trailing.
   If it does not succeed the result text is set to the special value -2.}


\cpar{Result text}{integer}

\item{\zprim{pop}{1}{{label}}}
\car{
   Pops a dictionary from the user dictionary stack pushed earlier
   by \pr{push#1}. The tag \zarg{label} must be same as the one
   supplied by that specific \pr{push#1} invocation.}

\cpar{Result text}{None.}


\item{\zprim{protect}{1}{{}}}
\car{
   The argument is expanded. Subsequently, all backslashes and curlies
   are escaped. The resulting text is put in place.}

\cpar{Result text}{
   \zarg{any} with backslashes and curlies escaped.}


\item{\zprim{push}{1}{{label}}}
\car{
   Pushes a new dictionary onto the user dictionary stack with tag
   \zarg{label}.  The corresponding \pr{pop#1} should use the same tag.  Note
   that \pr{defined#2} with the \v{lkey} directive checks only the top-level
   dictionary, whereas \pr{defined#2} with the \v{key} directive checks the
   whole stack of dictionaries.  Also, \pr{undef#1} only removes a key from the
   top-level dictionary. There is currently not a way to access keys based on
   dictionary label.}

\cpar{Result text}{None.}

\par{
   Example of usage:}

\verbatim{\
\\def{num}{1}
\\push{foo}
   \\def{num}{2}
   \\push{bar}
      \\def{num}{3}
      \\push{tim}
         \\def{num}{4}
      \\pop{tim}
      num is \\num
   \\pop{bar}
   num is \\num
\\pop{foo}
num is \\num}

\car{
   results in
   }

\verbatim{\
num is 3
num is 2
num is 1}


\item{\zprim{register}{2}{{tag}{any}}}
\car{
   Register \zarg{any} to be processed at the occassion specified by
   \zarg{tag}. The only \zarg{tag} currently supported is \v{END}.
   \v{END} registrees are processed only after all regular input has been
   processed.  Multiple \pr{register#2} invocations are allowed. Registrees are
   processed in the order of registration.}

\cpar{Result text}{
   None at time of registering, the result of \zarg{any} at time of
   processing.}

\item{\zprim{set}{2}{{key-sig}{any}}}
\car{
   As \pr{def#2} above, except that \pr{set#2} will not complain
   if the key labeled by \zarg{key-sig} already exists.}

\cpar{Result text}{None.}
\cpar{See also}{\pr{set#3}.}

\item{\zprim{setx}{2}{{key-sig}{}}}
\car{
 The second argument is expanded and stored in the key \zarg{key-name}.
 Besides simply storing the expansion of an expression, it can
 also be used to do trickier things as}

\verbatim{\
   \\def{bar}{klaas}
   \\setx{foo#2}{\\bar says \\1 and \\2}
   \\foo{x}{y}
   klaas says x and y}

\car{
 If you need lambda-like capabilities, take note that you can use \mc{!k} or
 \mc{!{\\k}} to construct a positional parameter\~\mc{k}, if you want to
 interpolate arguments into a key that will later take other arguments. Like
 this:}

\verbatim{\
   \\: is there any use for this wacky stuff?
   \\def{lambda#2}{\\setx{\\1#1}{\\2 says \\!1}}
   \\lambda{foo}{bar}
   \\foo{moo}
   bar says moo}

\car{
 Take care: the \pr{dofile#2} key outputs
 to the default output file. If you need to include the contents of
 a file within a \pr{setx#2} call, you need to use \pr{finsert#1} or \pr{zinsert#1}
 in conjunction with \pr{setx#2}.}

\cpar{Result text}{None.}
\cpar{See also}{\pr{set#3}.}


\: item{\zprim{set}{3}{{[{modes}{}][{if}{}][{unless}{}][{dict}{} and \v{}.
   The key will be set to its old value with a segment of length
   \v{} starting at offest \v{} replaced by \zarg{any}.
   Offsets are zero-based and units are in bytes.
   }

\cpar{Result text}{None.}
\cpar{See also}{\pr{def#2}, \pr{defx#2}, \pr{set#2}, \pr{setx#2}.}

\item{\zprim{special}{1}{{}}}
\car{
   \zarg{vararg} is expanded before use.
   It must have an even number of arguments.  These are
   interpreted as pairs. The first of each pair must enclose an integer in
   the range 0-255 or one of the special token identifiers \v{-1},
   \v{-2} or \v{-3}. The integers in the range 0-255 are interpreted as
   character indices The characters indexed \v{-1}, \v{-2}
   and \v{-3} correspond with the zoem glyphs\~\mc{~}, \mc{|}, and\~\mc{-}
   respectively.  The second element in each pair defines the string to
   which the character specified by the first element must be mapped.  This
   string is interpreted in device scope.  See the
   \capref{dscope} section for simple uses.}

\par{
   A key may occur multiple times. The corresponding definitions
   are stacked away and will be accessed according to the current
   \it{special level}
   (cf. the section on \iref{special}{mapped characters in device scope}).}

\par{
   Repeated use of \mc{special#1} does not cause the removal of previous
   definitions, with one exception: If \mc{special#1} is invoked
   with no arguments at all then all definitions are removed.}

\cpar{Note}{
Be sure to use delay sequences as appropriate, noting that vararg is expanded.
Below is how \aref{http://micans.org/pud/}{Portable Unix Documentation}
encodes a line break in troff:}

\verbatim{{-2} {\\!N.br\\!N}}

\car{
   Zoem interprets the value and accordingly associates
   the device scope sequence \v{\\N.br\\N} with the token \v{\\|}.
   The escape sequence \v{\\N} will thus be processed during
   the filter stage as is appropriate.
   Without the delay sequence zoem would try to expand \v{\\N} during
   processing of the \pr{special#1} primitive.}

\cpar{Result text}{None.}


\item{\zprim{switch}{2}{{}{vararg}}}
\car{
   The first argument is expanded. Subsequently, two arguments are successively
   taken from \zarg{vararg}. The first is expanded and string compared with
   \zarg{pivot}. If they match, the second argument is expanded and everything
   else is ignored.  If they do not match, the procedure is repeated.  If no
   (odd) argument matches, and the \zarg{vararg} has an odd number of
   arguments, the last argument is put in place.  It can be considered a
   failure clause.  This primitive does not have fall-through behaviour; at
   most one branch will be handed to the parser.}

\car{
   Different cases can be grouped in a vararg. If \pr{switch#2} recognizes
   that the test argument can be parsed as a vararg it will exctract all
   the corresponding sub-arguments. If the pivot matches any of these
   the branch corresponding to the test argument will be taken.}

\cpar{Result text}{
   Either the first block associated with a matching case of \zarg{pivot},
   the failure clause, or nothing at all.}


\item{\zprim{system}{3}{{cmd}{}{}}}
\car{
   \it{By default this primitive is disallowed.}
   The first argument is the name of a system command. The environment variable
   PATH is used in tracing the location of the command.  If \zarg{data} is
   non-empty, it is first \it{unprotected}, that is, escaped backslashes and
   curlies are unescaped.  The resulting text is then fed to command \zarg{cmd}
   with arguments \zarg{args}. The latter, if non-empty, must be
   specified as a vararg, even if only a single argument is present.
   Should execution of the command (be it with or
   without data) result in output on \stdout then the latter is captured,
   backslashes and curlies are escaped (i.e. the output is protected), and the
   result is put in place. \stderr  is the same as it is for the parent (zoem).}

\cpar{Note}{
   The security implications of this feature. By default
   zoem will \it{ignore} \mc{system}. The
   command line option \v{--unsafe} will cause zoem to prompt for user
   confirmation (if prompting is not possible it will ignore again) for
   each encountered \mc{system} invocation. The option \v{--unsafe-silent}
   will silently allow all \mc{system} invocations. The option
   \v{--allow=cmd[:cmd]*} explicitly specifies which commands to allow silently.
   It is also possible to use this option repeatedly rather than separate
   different commands by colons.}

\par{
   If the zoem command line option \v{--system-honor} is used, zoem will
   exit if a system command fails or is ignored.}

\par{
   A simple exit status is written in the variable \ssion{__sysval__}:
   it is zero (\v{0}) on success, and one (\v{1}) on failure.}

\par{
   Refer to \sibref{zoem}{the manual page of the zoem interpreter} for
   more information on \v{--unsafe}, \v{--unsafe-silent},
   \v{--allow=}, and \v{--system-honor}.}

\par{
   Built-in macros \mc{system#2} and \v{system#1} exist. The former
   drops the \zarg{data} argument, the latter also drops the \zarg{args}
   argument.}

\cpar{Example}{}
\verbatim{\\system{sort}{{-n}}{\\finsert{foo}}
\\system{ls}{{-l}{-a}}
\\system{date}}

\cpar{Result text}{
   The output captured (and then protected) from \zarg{cmd}'s \stdout, if any.}


\item{\zprim{table}{5}{{}{any1}{any2}{any3}{}}}
\car{
   The first argument is expanded and interpreted as an integer, say\~\v{k}.
   Successively, vectors of \v{k}\~elements are shifted from
   \zarg{vararg}. Each vector is bordered on the left with
   \zarg{any1}, bordered on the right with \zarg{any3}, and
   all elements in the vector are separated with \zarg{any2}.}

\par{
   This primitive is perhaps not really needed as its functionality
   is largely covered by \pr{apply#2}.}

\cpar{Result text}{
   The blocks from \zarg{vararg} interspersed in a table-like
   manner with \zarg{any1}, \zarg{any2}, and \zarg{any3}.}


\item{\zprim{textmap}{2}{{vararg}{}}}
\car{
   Apply one or more transformations to \zarg{any} and
   put the result in place.
   \zarg{vararg} takes a succession of key-value pairs.
   The associated transformation are applied in order. The
   supported transformations are:}

\begin{itemize}{
   {flow}{compact}
   {itemmargin}{5}
   {interitem}{0}
   {textindent}{6}
   {align}{right}
}
\item{{word}{ucase}}       Uppercase \zarg{any}
\item{{word}{lcase}}       Lowercase \zarg{any}
\item{{number}{roman}}       Convert number to Roman
\item{{number}{alpha}}       Convert number to letters
\item{{repeat}{}}        Concatenate  copies of \zarg{any}
\item{{caesar}{}}        Apply caesar encryption
\item{{vigenere}{}}      Apply vigenere encryption
\item{{vigenerex}{}}     Apply vigenere encryption and include space
\end{itemize}

\par{
   The roman transformation is e.g. used to equip the itemize
   environment (defined in the \sibref{../mac/generic_zmm}{generic package})
   with fancy roman numbering. To get uppercase roman,
   do this:}

\verbatim{\:{/}
   \\textmap{{number}{roman}{word}{ucase}}{\\your_nice_counter}}

\car{
   The alpha transformation maps its argument to a string over the alphabet \v{_a-z}, i.e.
   all the set of all lowercase letters with the underscore added.
   This set is simply used for counting in base\~27, with the underscore
   playing the role of zero.}

\cpar{Result text}{
   The transformed text.}


\item{\zprim{throw}{2}{{towel|error|done}{}}}
\car{
   Quit parsing, unwind stack until some occurrence of
   \pr{catch#2}, \pr{try#1} captures this throw.
   }

\par{
   The throw \mc{throw{done}} is also unconditionally caught by
   \pr{while#2} and \pr{eval#1}.
   If \mc{throw{done}} is encapsulated by neither of these four
   primitives it means that processing of the current file
   is stopped, and processing at the including file, if applicable,
   is resumed.
   }

\par{
   \zarg{any} is digested; if it has positive length the result
   is issued as a diagnostic.
   }

\cpar{Note}{
   Many primitives evaluate one or more of their arguments before use,
   as indicated in this manual.
   An occurrence of \mc{throw{done}} in such an argument, if not caught, will be
   treated like an error. It is possible to use \mc{throw{done}} in such
   an instance by encapsulating the argument in \pr{eval#1}.
   }


\cpar{Result text}{
   None, affects the result text of the embedding scopes.
   }
 
\item{\zprim{tr}{2}{{vararg}{}}}
\car{
   \zarg{vararg} contains key-value pairs. The accepted keys
   are \it{from} and \it{to} which must always occur together,
   and \it{delete} and \it{squash}. The values of these keys
   must be valid \it{translation} specifications.
   This primitive transforms \zarg{any} by successively applying
   translation, deletion and squashing in that order. Only the
   transformations that are needed need be specified.}

\par{
   The syntax accepted as translation specification is almost
   fully compliant with the syntax accepted by \bf{tr}(1), with
   three exceptions. First, repeats are introduced as
   \v{[*a*20]} rather than \v{[a*20]}. Second, ranges can (for
   now) only be entered as \v{X-Y}, not as \v{[X-Y]}.
   \v{X} and \v{Y} \it{can} be entered in either octal or
   hexadecimal notation (see further below).

   As an additional feature, the magic repeat operator \v{[*a#]} stops on both
   class and range boundaries.  Finally, character specifications can be
   complemented by preceding them with the caret \v{^}.  See further below for
   examples where these features are used.}

\cpar{Preprocessing}{
   The values (not the data \zarg{any}) are subjected to \unix tilde expansion
   as described in the \sibref{zoem}{tildexp}{the zoem manual}.}

\cpar{Syntax}{
   Specifications may contain ranges of
   characters such as \v{a-z} and \v{0-9}. Posix character classes
   are allowed. The available classes are}

\verbatim{\:{/}
   [:alnum:]
   [:alpha:]
   [:cntrl:]
   [:digit:]
   [:graph:]
   [:lower:]
   [:print:]
   [:punct:]
   [:space:]
   [:upper:]
   [:xdigit:]}

\par{
   Characters can be specified using octal notation, e.g.
   \mc{012} encodes the newline. Use \mc{173} for the opening curly,
   \mc{175} for the closing curly, \mc{134} for the backslash, and \mc{036} for
   the caret if it is the first character in a specification.  \it{DON'T} use
   \mc{\\}, \mc{\{}, or\~\mc{\}} in this case!  Hexadecimal notation is written
   as \mc{x7b} (the left curly in this instance).}

\cpar{Result text}{
   The expanded \zarg{any} subjected to the \v{tr} operator as specified.}

\cpar{Example}{
   The following was entered in interactive mode.}

\verbatim{\:{/}
\\tr{
   {from}{[:lower:][:upper:][:digit:][:space:][:punct:]}
   {to}{[*L#][*U#][*D#][*S#][*P#]}}{
 !"#$%&'()*+,-./0123456789:;<=>?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ
[\\\\]^_`
abcdefghijklmnopqrstuvwxyz
\\{|\\}~]}
.
----------------------------------------
SSPPPPPPPPPPPPPPPDDDDDDDDDDPPPPPPPSUUUUUUUUUUUUUUUUUUUUUUUUUUSPPPPPPSLLLLLLLLLLLLLLLLLLLLLLLLLLSPPPPP
----------------------------------------
\\tr{
   {squash}{^}
   {from}{[:lower:][:upper:][:digit:][:space:][:punct:]}
   {to}{[*L#][*U#][*D#][*S#][*P#]}}{
 !"#$%&'()*+,-./0123456789:;<=>?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ
[\\\\]^_`
abcdefghijklmnopqrstuvwxyz
\\{|\\}~]}
.
----------------------------------------
SPDPSUSPSLSP}

\car{Note how the magic repeat operator \v{[*#]} stops on class boundaries.}


\item{\zprim{trace}{1}{{}}}
\car{
   The argument is expanded and interpreted as an integer.  This integer
   encodes an ensemble of flags controlling the trace output. The different
   modes are exactly the same as those that can be set from the command line.
   Refer to the \iref{cline}{corresponding section} for more information.
   Special values are\~\v{0} (switch off all tracing),
   \v{-1} (switch on all tracing modes in short mode),
   \v{-2} (switch on all tracing modes in long mode),
   \v{-3} (switch to the previous tracing value),
   and \v{-4} emit a listing of tracing bits.
   The third can be useful to switch tracing on for a short while and then off
   again if you need to debug your document.
   Additionally and redundantly, \mc{trace#1} puts the previous tracing
   value in place.}

\cpar{Result text}{
   The previous tracing value.}


\item{\zprim{try}{1}{{any}}}
\car{
   This will process the content and
   output is written in the macro \ssion{__zoemput__}.  Output will
   be truncated in case \pr{throw#2} was used or an error occurred.
   The status, currently one of \v{done}, \v{towel}, or \v{error},
   is written in the session macro \ssion{__zoemstat__}.}

\cpar{Result text}{
   None.}


\item{\zprim{undef}{1}{{key-sig}}}
\car{
   Deletes the key with signature \zarg{key-sig} from the
   top level dictionary. Complains (but does not fail) if the key
   does not exist in that dictionary.
   It is possible to specify that a regular key (i.e. not a dollar key)
   must be looked up in the global dictionary by prefixing its
   signature with two single quotes.
   }

\cpar{Result text}{
   None.}


\item{\zprim{vanish}{1}{{any}}}
\car{
   This will only process the content for its side effects. Any result text is
   disregarded.  This allows easy free-style commenting of sequences of
   definitions.  By comparison, \pr{formatted#1} provides the means to give a
   formatted presentation of the definitions themselves.}

\cpar{Result text}{
   None.}


\item{\zprim{while}{2}{{condition}{any}}}
\car{
   While \zarg{condition} exands to something that is nonzero when interpreted
   as an integer, \zarg{any} is expanded and concatenated to the result text.
   The following piece of zoem asks the user for an integer and writes all
   Fibonacci numbers smaller than that integer plus one extra to \stdout.}

\verbatim{\
\\import{ctr.zmm}     \\: import ctr macros.
\\def{fib#1}{
   \\ctrset{a}{1}
   \\ctrset{b}{1}
   \\ctrset{c}{0}
   \\while{\\eqt{lq}{\\ctrput{c}}{\\1}}{
      \\ctrset{c}{\\ctrput{a}}
      \\ctrset{a}{\\let{\\ctrput{a}+\\ctrput{b}}}
      \\write{-}{txt}{\\ctrput{c}\\|}
      \\ctrset{b}{\\ctrset{c}}
   }
}

\\write{-}{txt}{Enter a number please, }
\\write{-}{txt}{then press  and \\|}
\\setx{num}{\\finsert{-}}    \\:  this reads from \stdin.
\\fib{\\num}}

\ccar{Note}{
   The strings built up by \pr{while#2} are internally concatenated
   until it is done, so the result from \pr{while#2} \it{can} be captured.
   This will make \pr{while#2} work for \pr{setx#2}.  If you want to output
   100M worth of lines or paragraphs in a while loop, either embed the stuff to
   be output in a \pr{write#3} call and make sure that no whitespace results
   from the loop (for example by using \pr{formatted#1}), or simply use
   \pr{whilst#2}. With \pr{write#3} you can specify a file name to which
   results should be output (use \ssion{__fnout__} for the current default output
   file) whereas \pr{whilst#2} simply outputs to the current default stream.}

\item{\zprim{whilst}{2}{{condition}{any}}}
\car{
   While \zarg{condition} exands to something that is nonzero when interpreted
   as an integer, \zarg{any} is expanded and \it{immediately output} to
   the current default output stream.}

\cpar{Result text}{
   None \- everything is sent to the default output stream right away.
   Output from \pr{while#2} \it{can} be captured, i.e. it can be that what
   is assigned by a \pr{setx#2} invocation.}


\item{\zprim{write}{3}{{}{str}{}}}
\car{
   The first argument is expanded and used as a file name.  It is a fatal error
   if the file has either not been opened by a previous \mc{write#3} call or
   cannot be opened for writing.  Two special file names or 'streams' are
   recognized, namely \v{-} and \v{stderr}. They map to \stdout
   and \stderr.
   The third argument is expanded, filtered, and written to file.  The second
   argument indicates the filter to be used. It must be one of the (literal)
   strings \v{copy}, \v{device}, or \v{txt}.}

\par{
   The \v{copy} filter does not filter anything at all (neither plain scope
   nor device scope) and does not touch any of the zoem escape sequences
   remaining after expansion.}

\par{
   The \v{device} filter does a full-fledged filtering of both parse scopes.
   It respects the settings according to the \pr{special#1}
   primitive. The write primitive associates unique metadata with each
   file it opens, so \it{at directives} such as\~\mc{N}, \mc{W}, and \mc{+}
   for different output files do not interfere with one another.
   Refer to the \secref{dscope} section for more information on
   at directives.}

\par{
   The \v{txt} filter maps \mc{\\} to \mc{} (i.e. a single
   backslash), \mc{~}\~to a single space, \mc{-}\~to a single hyphen,
   \mc{,} (the atomic separator) to nil, \mc{|}\~to a newline,
   \mc{\{}\~to\~\v{\{}, and\~\mc{\}} to\~\v{\}}. It copies everything
   else verbatim.}

\cpar{Result text}{
   Technically none, as the output of \pr{write#3} cannot be captured.}

\item{\zprim{writeto}{1}{{}}}
\car{
   Closes the current default output stream, and changes it to point to file
   \zarg{file name}. Useful when splitting a document into chapters, or god
   forbid, nodes.}

\cpar{Notes}{
   If the file name contains a path separator, zoem will refuse to carry
   on, because this may pose a risk that sensitive files are overwritten -
   in case someone has written a malicious zoem input file to do just that.
   If the option \v{--unsafe} is used, zoem will query the user
   what to do. If the option \v{--unsafe-silent} is used, zoem will
   merrily buzz on without querying.
   The path separator is entirely \unix-centric, i.e. a forward slash.}

\par{
   Zoem will recognize if \mc{writeto#1} is issued more than once for the same
   file \zarg{file-name}. On the first occassion, it will simply open the file
   and truncate any previous contents.  On the second occasion and onwards, it
   will append to the file.  There is currently no option to vary this
   behaviour.  Zoem will not recognize the fact that different strings might
   refer to the same file (e.g. \v{foo} and \v{./foo}). Whenever it encounters
   a file name not seen before, it will try to open the file in write mode.}

\par{
   In interactive mode, \mc{writeto#1} has no effect for text entered
   in plain mode. It \it{does} have effect in case \pr{write#3} is issued
   with \ssion{__fnout__} as the file name argument, since \mc{writeto#3}
   resets the \ssion{__fnout__} macro.}

\cpar{Result text}{
   None.}

\item{\zprim{zinsert}{1}{{}}}
\car{
   The contents of file \zarg{file name} are put in place unaltered
   enclosed by the \pr{!#1} delay primitive.  The contents must necessarily
   satisfy zoem syntax.  If the file can not be opened, the empty
   string results.
   See also \pr{finsert#1}.}

\cpar{Example}{}

\verbatim{\protect{\setx{foo}{\zinsert{mydata}}}
\protect{\setx{foo}{\eval{\zinsert{mydata}}}}}

\par{
   In the first case, \mc{foo} will contain the exact contents
   of file \v{mydata}. Those contents are first
   enclosed within the \pr{!#1} primitive by \pr{zinsert#1}.
   The resulting text is evaluated by \pr{setx#2} - the only
   thing this does is strip the enclosing \v{\\!{}} scope.}

\par{
   In the second case, \mc{foo} will contain the \it{evaluated}
   contents of file \v{mydata}, as \pr{eval#1} adds an additional
   layer of evaluation.}

\cpar{Note}{
   This primitive is able to read
   \iref{fileread}{inline files}, unlike \pr{finsert#1}.}
   
\cpar{Result text}{
   The contents of file \v{file name} or the empty string if
   file can not be opened.}

\end{itemize}

\sec1{pitfalls}{Pitfalls}
\par{
   This is a young section, with only few entries yet.}

\begin{itemize}{{flow}{compact}{align}{right}{interitem}{1}}
\item
\car{
   [\pr{system#3}] Beware that the argument/option list (the second
   argument of \mc{system#3}) is encoded
   as a vararg. If you have a single argument, it is easy to
   forget the enclosing curlies. In that case, zoem ignores the
   argument altogether.}

\par{
   Zoem protects the data returned by \mc{system#3}. So you may
   e.g. think (as I once did) that}

\verbatim{\protect{\system{date}{{%e}{%B}{%Y}}}}

\car{
   Is a neat way to create a vararg, but you will end up with
   something like}

\verbatim{\protect{\{24\}\{April\}\{2004\}}}

\item
\car{
   [Package authors] Beware of using \it{and} scope within \it{at} scope
   within a \mc{write#3} invocation that uses the copy filter.}

\verbatim{\protect{\write{file}{copy}{ foo \@{ zut \&{ bar }}}}}

\car{
   The \v{bar} part will not be evaluated as the copy filter does not apply the
   filtering stage. If the stuff written is read back in from some other part
   of the document, or from another document altogether, the \v{bar} part will
   be evaluated in a different context than the one in which it was created.}

\item
\car{
   \pr{throw#2} with argument \v{done} can be used to halt processing of the
   current file. Refer to the \pr{throw#2} description for the associated
   requirements.}

\end{itemize}


\sec1{glossary}{Glossary}

\par{
   For \bf{user keys}, \bf{dollar keys}, and \bf{dictionary stacks},
   refer to the \capref{dictionary} section and the \capref{macro} section.
   For \bf{data keys}, refer to the \secref{grape} section.}

\par{
   For \bf{key signatures} and \bf{key mention}, refer to the \capref{signature}
   section.  For \bf{anonymous keys}: the \capref{anonymous} section.}

\par{
   \bf{Session variables} are described in the \capref{session} section.}

\: funky looking macros such as \ssion{__searchpath__}
\: that either affect zoem's runtime behaviour (as  \ssion{__searchpath__} does)
\: or provide some information to the user
\: (e.g. \ssion{__fnin__} and \ssion{__fnbase__}).

\par{
   For \bf{varargs}, arguments in which a variable number of sub-arguments
   can be stored, and for \bf{blocks}: the \capref{vararg} section.}

\par{
   For \bf{plain scope}, \bf{device scope}, \bf{at scope}, and \bf{glyph
   sequences}: The \capref{dichotomy} and \capref{dscope} sections.}

\par{
   For file read and  \bf{inline files}: the \capref{fileread} section.}

\par{
 Sometimes zoem \it{protects} or \it{unprotects} data. Refer to the
 \capref{protection} section.}


\: mq
\end{simpledocument}

\done


zoem-11-166/doc/zoem.azm0000644000402500021140000006033111573124654011736 00000000000000
\'import{pud/man.zmm}
\'import{zoem.shared}

\begin{pud::man}{

   {name}{zoem}
   {html_title}{zoem}
   {author}{Stijn van Dongen}
   {section}{1}
   {synstyle}{long}
   {defstyle}{long}

   \man_share
}

\"pud::man::maketoc"


\'def{z#1}{\bf{\\\1}}
\'def{zoem}{\bf{zoem}}

\sec{name}{NAME}
\NAME{zoem}{macro processor for the Zoem macro/programming language.}

\sec{synopsis}{SYNOPSIS}

\par{
\zoem
   \synoptopt{-i}{[.azm]}{entry file name}
   \synoptopt{-I}{}{entry file name}
   \synoptopt{-o}{}{output file name}
   \synoptopt{-d}{}{set device key}}

\par{
\zoem\|
   (enter interactive mode - happens when none of \genopt{-i},
   \genopt{-I}, \genopt{-o} is given)}

\par{
\zoem
   \synreqopt{-i}{[.azm]}{entry file name}
   \synreqopt{-I}{}{entry file name}
   \synoptopt{-o}{}{output file name}
   \synoptopt{-d}{}{set device key}
   \synoptopt{-x}{enter interactive mode on error}
   \synoptopt{-s}{[=]}{set key to val}
   \synoptopt{-e}{}{evaluate any, exit}
   \synoptopt{-E}{}{evaluate any, proceed}
   \synoptopt{-chunk-size}{}{process chunks of size num}
   \synoptopt{--trace}{trace mode, default}
   \synoptopt{--trace-all-long}{long trace mode}
   \synoptopt{--trace-all-short}{short trace mode}
   \synoptopt{--trace-regex}{trace regexes}
   \synoptopt{-trace}{k}{trace mode, explicit}
   \synoptopt{--stats}{show symbol table stats after run}
   \synoptopt{--split}{assume \\writeto usage, set \\__split__}
   \synoptopt{--stress-write}{make \\write#3 recover}
   \synoptopt{--unsafe}{prompt for \\system#3}
   \synoptopt{--unsafe-silent}{simply allow \\system#3}
   \synoptopt{-allow}{cmd1[:cmdx]+}{allowable commands}
   \synoptopt{--system-honor}{require \\system#3 to succeed}
   \synoptopt{-nuser}{k}{user dict stack size}
   \synoptopt{-nenv}{k}{environment dict stack size}
   \synoptopt{-nsegment}{k}{maximum simple nesting depth}
   \synoptopt{-nstack}{k}{maximum eval nesting depth}
   \synoptopt{-buser}{initial user dict capacity}
   \synoptopt{-bzoem}{initial zoem dict capacity}
   \synoptopt{-tl}{k}{tab length}
   \synoptopt{-l}{}{list items}
   \synoptopt{-h}{show options}
   \synoptopt{--apropos}{show options}}

\sec{description}{DESCRIPTION}

\par{
   Zoem is a macro/programming language.  It is fully described in the
   \lref{zum.html}{Zoem User Manual} \'${roff}{(zum.html)}, currently available
   in HTML only. This manual page documents the zoem processor, not the
   zoem language.}

\par{
   If the input file is specified using the \optref{-i}{\genopt{-i} option} and
   is a regular file (i.e. not STDIN - which is specified by using a single
   hyphen), it must have the extension \v{.azm}.  This extension can but need
   not be specified.  The zoem key \z{__fnbase__} will be set to the file base
   name stripped of the \v{.azm} extension and any leading path components.
   If the input file is specified
   using the \optref{-I}{\genopt{-I} option}, no extension is assumed, and
   \z{__fnbase__} is set to the file base name, period.  The file base name is
   the file name with any leading path components stripped away.}

\par{
   If neither \useopt{-i} nor \useopt{-o} is specified, zoem enters interactive
   mode. Zoem should fully recover from any error it encounters in the input.
   If you find an exception to this rule, consider filing a bug report.  In
   interactive mode, zoem start interpreting once it encounters a line
   containing a single dot. Zoem's input behaviour can be modified by setting
   the key \z{__parmode__}.  See the section \secref{session} for the details.

   In interactive mode, zoem does \it{not} preprocess the interactive
   input, implying that it does not accept inline files and it does not
   recognize comments. Both types of sequence will generate syntax errors.
   Finally, readline editing and history retrieval can be used in interactive
   mode provided that they are available on the system. This means
   that the input lines can be retrieved, edited, and discarded with
   a wide range of cursor positioning and text manipulation commands.
   }

\par{
   From within the entry file and included files it is possible to open and
   write to arbitrary files using the \z{write#3} primitive.  Arbitrary files
   can be read in various modes using the \z{dofile#2} macro (providing four
   different modes with respect to file existence and output), \z{finsert#1},
   and \z{zinsert#1}.
   Zoem will write the default output to a single file, the name of which is
   either specified by the \genopt{-o} option, or constructed as described
   below.  Zoem can split the default output among multiple files.  This is
   governed from within the input files by issuing \z{writeto#1} calls. Refer
   to the \optref{--split}{\genopt{--split} option} and the
   \lref{zum.html}{Zoem User Manual}.}

\par{
   If none of \genopt{-i} or \genopt{-o} is given, then zoem will enter
   interactive mode. In this mode, zoem interprets by default chunks of
   text that are ended by a single dot on a line of its own.  This can be
   useful for testing or debugging.  In interactive mode, zoem should recover
   from any failure it encounters. Interactive mode can also be accessed from
   within a file  by issuing \mc{zinsert{stdia}}, and it can be triggered as
   the mode to enter should an error occur (by adding the
   \optref{-x}{\genopt{-x} option} to the command line).}


\par{
   If \genopt{-o} is given and \genopt{-i} is not,
   zoem reads input from STDIN.}

\par{
   If \genopt{-i} is given and \genopt{-o} is not, zoem will construct an
   output file name as follows.  If the \genopt{-d} option was used with
   argument \v{}, zoem will write to the file which results from
   expanding \z{__fnbase__.}.  Otherwise, zoem writes to (the expansion
   of) \z{__fnbase__.ozm}.}

\par{
   For \genopt{-i} and \genopt{-o}, the argument \v{-}
   is interpreted as respectively \v{stdin} and \v{stdout}.}

\sec{options}{OPTIONS}

\'begin{itemize}{{interitem}{1}}

\item{\defopt{-i}{[.azm]}{entry file name}}
\car{
   Specify the entry file name. The file must have the \v{.azm}
   extension, but it need not be specified.}

\item{\defopt{-I}{[.azm]}{entry file name}}
\car{
   Specify the entry file name, without restrictions on the file name.}

\item{\defopt{-o}{}{output file name}}
\car{
   Specify the output file name.}

\item{\defopt{-d}{}{set key \\__device__}}
\car{
   Set the key \z{__device__} to \v{}.}

\item{\defopt{-x}{enter interactive mode on error}}
\car{
   The afterlife option. If zoem encounters an error during
   regular processing, it will emit error messages as usual,
   and then enter interactive mode. This allows you e.g.
   to inspect the values of keys used or defined within
   the problematic area.}

\item{\defopt{-s}{[=]}{set key to val}}
\car{
   Set the key \z{key} to \bf{val} if present, \bf{1} otherwise.
   Any type of key can be set, including keys taking arguments and keys
   surrounded in quotes.  Beware of the shell's quote and backslash
   interpolation.
   Currently \bf{val} is not evaluated, so appending or prepending
   to a key is not possible.
   }

\item{\defopt{-e}{}{evaluate any, exit}}
\car{
   This causes zoem to evaluate \v{},
   write any result text to stdout, and exit.}

\item{\defopt{-E}{}{evaluate any, proceed}}
\car{
   This causes zoem to evaluate \v{},
   write any result text to stdout, and proceed e.g. with
   the entry file or an interactive session.}

\item{\defopt{-chunk-size}{}{process chunks of size num}}
\car{
   Zoem reads its input in chunks. It fully processes a chunk before moving on
   with the next one.  This option defines the
   (minimum) size of the chunks.  The size or count of the
   chunks does not at all affect zoem's output. The default minimum
   chunk size equals one megabyte.}

\par{
   Zoem will read files in their entirety before further processsing
   if \useopt{-chunk-size}{0} is specified.}

\par{
   Zoem does not chunk input files arbitrarily. It will append to
   a chunk until it is in the outermost scope (not contained within
   any block) and the chunk will end with a line that was fully read.}

\par{
   Consequently, if e.g. a file contains a block (delimited by
   balanced curlies) spanning the entire file then zoem is forced
   to read it in its entirety.}

\item{\defopt{--trace}{trace mode, default}}
\car{
   Trace in default mode.}

\item{\defopt{--trace-all-long}{long trace mode}}
\car{
   Sets on \it{most} trace options in long mode.
   Trace options \v{xxx} not set
   have their own \genopt{--trace-xxx} entry (see below).}

\item{\defopt{--trace-all-short}{short trace mode}}
\car{
   Sets on \it{most} trace options in short mode.
   Trace options \v{xxx} not set
   have their own \genopt{--trace-xxx} entry (see below).}

\item{\defopt{--trace-keys}{trace keys}}
\car{
   Trace keys.}

\item{\defopt{--trace-regex}{trace regexes}}
\car{
   Trace regexes (i.e. the \z{inspect#4} primitive).}

\item{\defopt{-trace}{k}{trace mode, explicit}}
\car{
   Set trace options by adding their representing bits.}

\item{\defopt{--stress-write}{stress test using write}}
\car{
   This makes \z{write#3} recover from errors.
   It is a special purpose option used for creating zoem
   stress test suites, such as \v{stress.azm}
   in the zoem distribution \v{/examples} subdirectory.}

\items{
   {\defopt{--unsafe}{prompt for \\system#3}}
   {\defopt{--unsafe-silent}{simply allow \\system#3}}
   {\defopt{-allow}{cmd1[:cmdx]+}{allowable commands}}
}
\car{
   With \useopt{--unsafe} system calls are allowed but the user
   is prompted for each invocation. The command and its arguments (if any)
   are shown, but the STDIN information (if any) is withheld.
   With \useopt{--unsafe-silent} system calls are allowed and
   the user is never prompted.}

\par{Use \genopt{-allow}{str} or \genkvp{--allow}{str} to
   specify a list of allowable commands, as a string
   in which the commands are separated by colons.}

\item{\defopt{--system-honor}{require \\system#3 to succeed}}
\car{
   With this option any \mc{system#3} failure (for whatever reason,
   including safe behaviour) is regarded as a zoem failure.
   By default, failing system calls are ignored under either
   safe mode, unsafe mode (--unsafe), or silent unsafe mode
   (--unsafe-silent).}

\item{\defopt{--split}{assume split output}}
\car{
   This assumes zoem input that allows output to multiple files (e.g.
   chapters).  It sets the default output stream to \v{stdout} (anticipating
   custom output redirection with \z{writeto#1}) and sets the session macro
   \z{__split__} to \v{1}.}

\item{\defopt{--stats}{show symbol table stats after run}}
\car{
   Show symbol table chacteristics. Symbol tables are
   maintained as hashes.}

\item{\defopt{-tl}{k}{set tab length}}
\car{
   Set the tab length. HTML output can be indented according
   to nesting structure, using tabs which are expanded
   to simple spaces. By default, the tab length is zero,
   meaning that no indent is shown.
   The maximum value the tab length can be set to is four.}

\items{
   {\defopt{-nsegment}{k}{level of macro nesting allowed}}
   {\defopt{-nstack}{k}{stack count}}
   {\defopt{-nuser}{k}{user dictionary stack size}}
   {\defopt{-nenv}{k}{environment dictionary stack size}}
   {\defopt{-buser}{k}{initial user dict capacity}}
   {\defopt{-bzoem}{k}{initial zoem dict capacity}}
}
\car{
   Probably needed only if you have some obscure and extreme use
   for zoem. The segment limit applies to simple nesting of macros. The
   stack limit applies to nesting of macros that evaluate an argument before
   use. Each such evaluation creates a new stack.  The user limit applies to
   \z{push{user}}, the env limit applies to the nesting level of environments
   (started with \mc{begin#2}). The user
   dict capacity pertains to the initial number of buckets allocated for
   user and environment dictionaries, and the zoem dict capacity pertains to the
   dictionary containing the zoem primitives.}

\item{\defopt{-l}{}{list items}}
\car{
   List items identified by \v{}. It can be any of
   \bf{all},
   \bf{filter}.
   \bf{legend},
   \bf{builtin},
   \bf{session},
   \bf{trace}, or
   \bf{zoem},

   Multiple identifiers
   can be joined in a string, e.g.  \v{-l legendzoem} prints a legend
   followed by a listing of zoem primitives.}

\item{\defopt{-h}{show options}}
\car{
   Show short synopsis of options.}

\'end{itemize}


\sec{session}{SESSION MACROS}

\'begin{itemize}
\item{\z{__parmode__}}
   This macro affects zoem's read behaviour in interactive mode.
   It can be set on the command line using the \genopt{-s} option.
   Bits that can be set:

\verbatim{\
1    chomp newlines (remove the newline character)
2    skip empty newlines
4    read paragraphs (an empty line triggers input read)
8    newlines can be escaped using a backslash
16   read large paragraphs (a single dot on a line
     triggers input read)}

\item{\z{__device__}}
\car{
   The current output device, set by \optref{-d}{the command line option
   \genopt{-d}}.  The \bf{man} and \bf{faq} packages support \bf{html} and
   \bf{roff} as its values.}

\item{\z{__fnbase__}}
\car{
   The base name of the input file name. Leading path components are stripped
   away.  If the \genopt{-i} option is used the input file is required to have
   the \v{.azm} suffix. In that case the suffix is also stripped to obtain the
   base name.}

\item{\z{__fnentry__}}
\car{
   The name of the entry file.}

\item{\z{__fnin__}}
\car{
   The file currently being processed.}

\item{\z{__fnout__}}
\car{
   The name of the default output file.}

\item{\z{__fnpath__}}
\car{
   The leading component of the input file name, possibly empty.}

\item{\z{__fnup__}}
\car{
   The file that included the current file, if applicable.}

\item{\z{__fnwrite__}}
\car{
   This key is set by \mc{write#3} to its first argument. It can be used by
   macros that are expanded during evaluation of the third argument. Possible
   usage is to branch on the name of the \it{write} output stream. For example
   a file called \it{index.html} may be treated differently from other files.
   The key is deleted afterwards. Nested invocations of \mc{write#3} may
   corrupt the status of this key.}

\item{\z{__ia__}}
\car{
   The input/output separator used in interactive mode.}

\item{\z{__line__}}
\car{
   The line number in the file currently being processed.
   This number will be correct for any invocation outside the scope
   of a macro. For any invocation within a macro the result will be
   the line number of the closing curly of the outermost containing
   macro. The following}

\verbatim{\protect{\:/
   \__line__
   \__line__
   \__line__
   \group{
   \__line__
   \group{\__line__}
   \__line__}}}

\par{Results in}

\verbatim{\:/
   1
   2
   3
   7
   7
   7}

\item{\z{__searchpath__}}
\car{
   A vararg containing a list of paths to search when a file is to be
   included/imported/read/loaded.  When you start zoem, this key should
   contain the location of the \bf{man.zmm} and \bf{faq.zmm} package files.
   It is advisable not to overwrite this key but to append to it instead.}

\item{\z{__zoemstat__}}
\car{
   Set to one of \v{ok}, \v{towel} (that one is a bit lame),
   or \v{error} by either the interpreter, an occurrence of \mc{catch#2},
   or \mc{try#1}.}

\item{\z{__zoemput__}}
\car{
   Set by \mc{try#1} to the possibly truncated result of processing
   its argument.}

\item{\z{__lc__}}
\car{
   Expands to a left curly. It is hard to find a need for this \- the zoem
   stress suite uses it to generate a particular syntax error at a deeper
   interpretation level.}

\item{\z{__rc__}}
\car{
   Expands to a right curly.}

\'end{itemize}


\sec{set}{THE SET MODIFIERS}

\par{The \mc{set#3} primitive allows a \v{{modes}{}}
   directive in its first argument. Here \genarg{}
   can be a combination of single-letter modifiers, each
   described below.

   }

\itemize_set3_modifiers

\sec{inspect}{THE INSPECT SUBLANGUAGE}

\par{
   The \mc{inspect#4} primitive takes four arguments. The languages
   accepted by the first two arguments are described below. The third
   argument is a replacement string or a replacement macro accepting
   back-references (supplied as an anonymous macro). The fourth
   argument is the data to be processed.}

\cpar{arg 1}{
   Is a vararg. Currently it accepts a single key
   \it{mods} for which the value should be a comma-separated list over the words
      \it{posix},
      \it{icase},
      \it{dotall},
      \it{iter-lines}
      \it{iter-args},
      \it{match-once},
      \it{discard-nmp},
      \it{discard-nil-out},
      \it{discard-miss},
      \it{count-matches}.
   Alternatively repeated use of \it{mods} is allowed.}

\cpar{arg 2}{
   Is a regular expression. Tilde patterns
   are expanded according to all of the ZOEM, UNIX, and REGEX schemes.
   Refer to \secref{tildexp} for these.}

\par{
   The third argument is a constant string or an anonymous key,
   the fourth argument is data.}

\sec{tr}{THE TR SUBLANGUAGE}

\par{
   The \mc{tr#2} primitive takes two arguments. The first argument contains
   key-value pairs. The accepted keys are \it{from} and \it{to} which must
   always occur together, and \it{delete} and \it{squash}.
   The values of these keys must be valid \it{translation} specifications.
   This primitive transforms the data in the second argument by successively
   applying translation, deletion and squashing in that order. Only the
   transformations that are needed need be specified.}

\par{
   Translation specifications are subjected to UNIX tilde expansion as
   described below.}

\par{
   The syntax accepted by translation specifications is almost
   fully compliant with the syntax accepted by \bf{tr}(1), with
   three exceptions. First, repeats are introduced as
   \v{[*a*20]} rather than \v{[a*20]}. Second, ranges can (for
   now) only be entered as \v{X-Y}, not as \v{[X-Y]}.
   \v{X} and \v{Y} \it{can} be entered in either octal or
   hexadecimal notation (see further below).

   As an additional feature, the magic repeat operator \v{[*a#]} stops on both
   class and range boundaries.  Character specifications can be
   complemented by preceding them with the caret \v{^}.
   }

\par{
   Specifications may contain ranges of characters such as \v{a-z} and \v{0-9}.
   Posix character classes are allowed. The available classes are}

\verbatim{\:{/}
   [:alnum:]
   [:alpha:]
   [:cntrl:]
   [:digit:]
   [:graph:]
   [:lower:]
   [:print:]
   [:punct:]
   [:space:]
   [:upper:]
   [:xdigit:]}

\par{
   Characters can be specified using octal notation, e.g.
   \mc{012} encodes the newline. Use \mc{173} for the opening curly,
   \mc{175} for the closing curly, \mc{134} for the backslash, and \mc{036} for
   the caret if it is the first character in a specification.  \it{DON'T} use
   \mc{\\}, \mc{\{}, or\~\mc{\}} in this case!  Hexadecimal notation is written
   as \mc{x7b} (the left curly in this instance).}

\par{
   See \secref{examples} for an example of \v{tr#2} usage.}

\sec{tildexp}{TILDE EXPANSION}

\par{
   Some primitives interface with UNIX libraries that require backslash escape
   sequences to encode certain tokens or characters.  The backslash is special
   in zoem too and without further measures it can become very cumbersome to
   encode the correct escape sequences as it is not always clear which tokens
   should be escaped or unprotected at what point. It is especially difficult
   to handle the zoem characters with special meaning, \v{\{}, \v{\}} and
   \mc{}.}

\par{
   The two primitives under consideration are \z{inspect#4} and \z{tr#2}.
   Both treat the tilde as an additional escape character for certain arguments
   (as documented in the user manual). These arguments are subjected to tilde
   expansion, where the tilde and the character it proceeds are translated to a
   new character or character sequence. There are three different sets of tilde
   escapes, ZOEM, UNIX and REGEX escapes. \z{tr#2} only accepts UNIX escapes,
   \z{inspect#4} accepts all.  Tilde expansion is always the last processing
   step before strings are passed on to external libraries.}

\par{The ZOEM scheme contains some convenience escapes, such
as \v{~E} to encode a double backslash.}


\par{\bf{ZOEM tilde expansion}}

\verbatix{\bf{\'protect{\:/
 meta sequence   replacement
.-----------------------------.
|     ~~       |      ~       |
|     ~E       |      \\      |
|     ~e       |      \       |
|     ~I       |      \{      |
|     ~J       |      \}      |
|     ~x       |      \x      |
|     ~i       |      {       |
|     ~j       |      }       |
`-----------------------------'}}}

\car{The zoem tr specification language accepts \mc{x**} as hexadecimal
notation, e.g. \mc{x0a} denotes a newline in the ASCII character set}.

\par{\bf{UNIX tilde expansion}}

\verbatix{\bf{\'protect{\:/
 meta sequence   replacement
.-----------------------------.
|     ~a       |      \a      |
|     ~b       |      \b      |
|     ~f       |      \f      |
|     ~n       |      \n      |
|     ~r       |      \r      |
|     ~t       |      \t      |
|     ~v       |      \v      |
|     ~0       |      \0      |
|     ~1       |      \1      |
|     ~2       |      \2      |
|     ~3       |      \3      |
`-----------------------------'}}}

\par{\bf{REGEX tilde expansion}}

\verbatix{\bf{\'protect{\:/
 meta sequence   replacement
.-----------------------------.
|     ~^       |      \^      |
|     ~.       |      \.      |
|     ~[       |      \[      |
|     ~$       |      \$      |
|     ~(       |      \(      |
|     ~)       |      \)      |
|     ~|       |      \|      |
|     ~*       |      \*      |
|     ~+       |      \+      |
|     ~?       |      \?      |
`-----------------------------'}}}


\sec{environment}{ENVIRONMENT}
\par{
   The environment variable ZOEMSEARCHPATH may contain a colon and/or
   whitespace separated list of paths. It will be used when searching
   for files included via one of the \v{dofile} aliases
   \mc{input}, \mc{import}, \mc{read}, and \mc{load}.
   Note that the zoem macro \mc{__searchpath__} contains the location where
   the zoem macro files were copied at the time of installation of zoem.}

\sec{diagnostics}{DIAGNOSTICS}
\par{
   On error, Zoem prints a file name and a line number to which it was able to
   trace the error.  The number reported is the same as the one stored in the
   session macro \mc{__line__}.  For an error-trigering macro which is not
   nested within another macro the line number should be correct. For a macro
   that does occur nested within another macro the line number will be the line
   number of the closing curly in the outermost containing macro.}

\par{
   If in despair, use one of the tracing modes, \bf{--trace-keys} is one of the
   first to come to mind. Another possibility is to supply the
   \optref{-x}{\genopt{-x} option}.}

\sec{bugs}{BUGS}
\par{
   No known bugs. \z{inspect#4} has not received thorough stress-testing,
   and the more esoteric parts of its interface will probably change.}


\sec{seealso}{SEE ALSO}
\par{
   \aref{http://micans.org/aephea/}{Aephea}
   is a document authoring framework largely for HTML documents.
   }

\par{
   \aref{http://micans.org/pud/}{Portable Unix Documentation}
   provides two mini-languages for authoring in the unix environment. These
   languages, pud-man and pud-faq are both written in zoem.}


\sec{examples}{EXAMPLES}
\par{
   This is a relatively new section, aimed at assembling useful or explanatory snippets.
   }

\par{
   Create a vararg containing file names matching a pattern (\v{png} in
   this example).}

\verbatim{\protect{\:{/}
\setx{images}{
   \inspect{
      {mods}{iter-lines,discard-miss}
   }{(.*~.png)}{_#1{{\1}}}{\system{ls}}
}}}

\par{
   Use magic boundary stops with \v{tr#2}.}

\verbatim{\:{/}
\\tr{
   {from}{[:lower:][:upper:][:digit:][:space:][:punct:]}
   {to}{[*L#][*U#][*D#][*S#][*P#]}}{
 !"#$%&'()*+,-./0123456789:;<=>?@
ABCDEFGHIJKLMNOPQRSTUVWXYZ
[\\\\]^_`
abcdefghijklmnopqrstuvwxyz
\\{|\\}~]}}


\sec{author}{AUTHOR}
\par{
   Stijn van Dongen.}

\={eekzoo}
\'write{stderr}{device}{In file eekzoo at line count \__line__\@{\N}}
\'write{stderr}{device}{In file eekzoo at line count \__line__\@{\N}}
\==

\={foobar}
\'write{stderr}{device}{In file foobar at line count \__line__\@{\N}}
\'write{stderr}{device}{In file foobar at line count \__line__\@{\N}}
\==

\'input{eekzoo}
\'input{foobar}

\end{pud::man}

zoem-11-166/doc/zum.html0000644000402500021140000077422111576103407011762 00000000000000






Zoem User's Manual


June 15, 2011
Zoem User's Manual
Introduction

Zoem: <Dutch> The sound made by electrical devices and flying bugs. Pronounced: zoom or zum; the vowel is short.

Zoem is a general macro/programming language with filtering capabilities. It transforms text in two stages.

In the first stage the text is scanned for macro escape sequences. The core zoem language consists of so-called primitive macros. They provide a wide spectre of functional behaviour, including data storage, arithmetic evaluation, I/O facilities, iteration and flow control, dictionary stacks, system interaction, and regular expressions. As with any macro/programming language, the real power comes from the ability to create new user-defined macros in terms of primitives and other user-defined macros. Macro expansion can be arbitrarily delayed, and inside-out evaluation is supported.

A useful feature is the combination of anonymous macros, lists, and the \apply#2 primitive, constituting a kind of callback mechanism in zoem. Another feature is the automatic popping and pushing of dictionaries with the begin/end environment, providing shadowing and localization.

In the optional second stage, the text is filtered. Two filter scopes are distinguished. The first is called device scope and is always enclosed in a filter escape sequence. The second, plain scope, is everything else. Filtering mechanisms are provided for both. The filtering language is useful when the output is meant to be in an external format with device-specific escape sequences, such as HTML or troff. Conversions are specified in device specific filtering rules that are applied in plain scope, so that the zoem input is device agnostic. By setting up different filtering rules the same input can be used to generate different outputs.

This manual covers the whole zoem language. A large part of it is only interesting for someone writing a reusable macro package. A smaller part is still interesting for someone who is just using such a package, but might want to add some utilities and shortcuts of his own. The part where file inclusion, macro definitions, and macro expansions are explained is required reading for anyone considering or planning to use zoem.

Other documentation

The manual page of the zoem interpreter.

Zoem is used by Portable Unix Documentation (PUD) and Aephea. The latter is a general authoring tool for writing HTML documents and provides both useful abstractions and a framework for creating new abstractions. It uses and promotes the use of CSS. A small core of Aephea has been ported to the typesetting language troff. This core is used in PUD, which provides mini-languages for FAQ documents and UNIX manual pages. Documents written in PUD can be output to troff and html, and further to plain text, PostScript, and PDF.

About this document

Clicking on the number next to a section title (e.g. the 1.2 to the right of the title About this document of this section) will get you to the corresponding section of the table of contents.

Zoem input and zoem output are both generally shown in a typeface font, like this.

Links that point to locations within this document are shown in blueish colors. Links that point to documents originating from the same package (project) or perhaps the same site are shown in in greenish colors. Links that point to other stations on the internet or perhaps other packages on the same site are shown in in reddish colors.

Table of Contents
Zoem in a nutshell

Zoem supports several programming constructs, immediate and postponed expansions, stream character filtering, easy I/O facilities, integer arithmetic, and a whole lot more. Its main aims are:

Providing the building blocks for a structural and programmable approach. Section 3.1 contains an overview of the zoem primitives and their use.

Accepting a pleasant syntax that does not require much thinking, favouring simplicity and rigor over looseness and context dependent rules.

Creation from the keyboard while minimizing on key-strokes.

Few meta characters. Zoem achieves this by having a single special character and a reasonably restricted syntax.

Adding filtering capabilities so that multiple devices can be addressed.

Expressive power (features)

Listed below are some features of the zoem primitives. In practice there are two kinds of zoem files. The first is a zoem macro file, which should contain macros defined in terms of lower-level macros, with zoem primitives at the lowest level. The second is a zoem document file, which should import such a macro file and only use the high-level macros defined in that macro file. Additionally, a document file can define some high-level macros of its own, in terms of low-level macros, zoem primitives, or a mixture of both.

Macros with arguments, overloading of key names allowed (i.e. different keys with the same name are distinguished by the number of arguments they take). (\def#2, \set#2, and \setx#2). Zoem primitives look like regular macros, but usually they expand their arguments before use. User macros can be equipped with this behaviour by wrapping them in \apply#2.

Support for variable number of arguments - see the vararg section.

Easy file, STDIN, STDOUT, and STDERR input/output, nested file inclusion (\dofile#2, \write#3, \finsert#1, and \zinsert#1).

Extensive support for arithmetic with the primitives \let#1, \f#2, \f#3, \fv#2, and \eqt#3.

Operators returning booleans (\defined#2, \cmp#3, \eqt#3), control operators acting on those (\while#2, \if#3).

The for-like primitives \apply#2 and \table#5.

Match and substitution capabilities using POSIX regexes (\inspect#4).

Register macros with \register#2 to be processed after regular processing (e.g. to output counters or warnings).

The switch primitive \switch#2, employing the vararg construct.

Localized expansions (\eval#1) and meta-zoem (\! and \!#1).

A user dictionary stack that can be manipulated using \push#1 and \pop#1. An environment environment for doing \begin{stuff} .. \end{stuff} stuff (see \env#4). This environment creates name scopes by pushing and popping to/from the dollar dictionary stack. Environments may take arguments, one particular useful application is that local variables (e.g. local to an itemize environment) can thus be specified by the user.

Storage of data by multiple string indexing — arbitrary data can be stored in a tree by indexing nodes with (arbitrary) strings. Refer to the Tree data section.

The ability to nicely format macros (see \formatted#1).

Syntactic sugar for writing SGML-style mark-up and having it checked.

Executing system commands, possibly sending data to STDIN and receiving data from STDOUT\system#3.

And more.

Invoking zoem from the command line

You use zoem by invoking it from the command line. The normal mode of operation is that you specify a file for zoem to chew up and spit out. This is called the entry file, and its name usually has the extension .azm. A common invocation looks as follows:

zoem -i mcl.azm

The -i flag specifies the entry file. It is not necessary to write the .azm extension, zoem will append it for you. The preceding could also have been entered as

zoem -i mcl

In either case, zoem will set the session key \__fnbase__ to the base name of the entry file, i.e. the name stripped of its .azm suffix and any leading path components. In this example, the key \__fnbase__ will get the value mcl. If you have an input file without the .azm extension, you need to use the -I option.

Zoem writes its output to a default output file which is named according to three rules. The rules are:

If the -o flag was given the value say somestr, zoem will write to the file named somestr.

If -o was not supplied but the -d flag was used with argument say zyx, zoem will write to the file named \__fnbase__.zyx. The -d flag also results in the macro \__device__ being set to xyz.

If neither -d nor -o was given, zoem will write to the file named \__fnbase__.ozm.

It is possible to change the default output file from within the document; this is achieved with the \writeto#1 primitive. Zoem can mingle default output with output to other files, use the \write#3 primitive for that.

Both the -i and -o flag accept a hyphen as argument, meaning respectively that zoem will read from STDIN and write to STDOUT.

Specifying just zoem and entering a return will cause zoem to enter interactive mode, in which it reads from STDIN and writes to STDOUT. Interactive mode currently should catch any errors occurring, so it is a good way of experimenting and testing. By default, interactive mode reads chunks that are ended by a single dot on a line by itself. This behaviour can be changed by setting the session variable \__parmode__ using the -s option. Using zoem -l parmode shows the bits that can be set in this variable. It is for example possible to make zoem read paragraphs (ended by two or more consecutive newlines).

Note
There is a difference between specifying no output stream (i.e. not using the -o option) and explicitly specifying -o -. In the latter case, zoem will never enter interactive mode. Should you need to insert zoem into some pipe sequence, then you need to use -o -.

Tracing errors
If your document contains erroneous input (e.g. using a macro that was never defined), zoem will by default print the approximate corresponding line number of the current input file and the last key it saw, and then exit. If that does not suffice in tracking down the error, you have a choice of options. One possibility is to use one of the various tracing modes described below and in the zoem interpreter manual. Another possibility is to specify the -x option which says to enter interactive mode should an error occur. This enables you to inspect the values of keys defined or used in the problematic area. A selection of other options is given below. For the full story, consult the manual page of the zoem interpreter.

-h

lists all flags accepted by zoem with a short description for each.

 
-s <foo>=<bar>

Sets key \foo to bar.

 
-e <any>

Zoem will evaluate <any>, writing any result text to STDOUT, and then exit.

 
-E <any>

Zoem will evaluate <any>, writing any result text to STDOUT, and then proceed.

 
-x

If an error occurs, zoem stops processing and enters interactive mode.

 
-l <str>

lists all entities specified by <str>. It can be any of all, filter, legend, alias, session, trace, or zoem. Repeated use is allowed. In fact, zoem will only check whether the target is present as a substring, so

zoem -l legendzoem

will print the legend and the list of zoem primitives.

 
--trace

This traces (prints) all keys encountered, and prints possibly truncated arguments. Zoem has several other tracing flags, use the -h flag or refer to the zoem manual page for more information.

Tracing can be set from within the document using the \trace#1 primitive. Part or whole of the data tree can be output from within the document using the \%dump primitive (refer to the Tree data section).

 
--stats

When zoem is done, it prints statistics about the primitive name table and about the user name table.

Zoem syntax and parsing
Syntax and nomenclature

Zoem parses text which may contain zoem escape sequences, these are sequences that have special meaning and cause zoem to do special processing. Each and every escape sequences starts with a backslash, no exceptions. There are three kinds of sequences that are macros, which may or may not take arguments. These are zoem primitives, user keys, and dollar keys.

There are currently about sixty zoem primitives, these are listed in the The zoem language section. Sixty is quite a lot; it includes convenience sibling sets such as \set#2, \setx#2, \def#2, and \def#2, and entries covering a variety of areas such as I/O, arithmetic, testing, control, string conversions, formatting, shadowing (scopes), and all the other stuff listed in the Topic index section.

Additionally there are a number of zoem built-ins that are defined in terms of primitives. Built-ins live in the same dictionary as primitives and behave the same in all aspects. The next section has some further remarks on the differences and resemblances between primitives/built-ins on the one hand and user macros on the other hand.

User keys and dollar keys are discussed in the Macro expansion section. Arguments are shipped by delimiting them with curly braces, as in

\thiskey{takes}{\bf{two}\it{arguments}}.

No characters are allowed inbetween (the delimiting curlies of) two arguments (but take note of the handy \formatted#1 primitive). See the Macro expansion section for more information. Zoem is very strict in the syntax it accepts, but it garantuees to accept a text in which each backslash \ is escaped as \\ (i.e. a text in which all consecutive runs of backslashes have even length).

An active backslash is any backslash that is not made inactive by an active backslash immediately preceding it. The first backslash seen by zoem (proceeding sequentially through the text) is active. This is one incomprehensible way of stating the obvious, and I bet you know what I mean anyway. An active backslash must always have a meaning known to zoem. If zoem does not get it, it will complain and exit. The meaning (i.e. class) of the escape sequence introduced by an active backslash is determined by the character immediately following it. A list is given below.

Within arguments, curlies not functioning as argument delimiters must also be escaped if they are not balanced. It is best practice to escape all non-argument-delimiting curlies, but I never do so myself unless they are not balanced. An escaped curly is a curly preceded by an active backslash. An active curly is a curly that is not escaped. A pair of balanced curlies consists of an active left curly that matches an active right curly, where inbetween all escaped curlies are disregarded. A block is anything delimited by balanced curlies. The word scope is most often used to distinguish between device scope and plain scope, these are the two kinds of parse scopes. An environment scope refers to the stuff enclosed by instances of the \begin#2 and \end#1 primitives. So called name scopes are entered and exited by \push#1 and \pop#1.

Primitives, built-ins and user macros

Zoem distinguishes between primitives and built-ins and user macros on the other hand. Consider the following slightly contrived example.

\def{fib#1}{ \push{fibonacci} \set{a}{1} \set{b}{1} \set{c}{0} \while{\let{\a <= \1}}{ \setx{c}{\a} \setx{a}{\let{\a + \b}} \write{-}{txt}{\c\|} \setx{b}{\c} } \pop{fibonacci} }

The example is contrived in that zoem is not the most appropriate language to compute Fibonacci numbers. The reason for using it is that extracts from existing macro packages require more context and are simply more boring.

In the example, the following macros are primitives: \push#1, \pop#1, \def#2, \set#2, \while#2, \let#1, \setx#2, and \write#3. The example defines a user macro \fib#1, which can be invoked e.g. as \fib{100}. Doing this either from a file or from interactive mode should give the output below.

1 2 3 5 8 13 21 34 55 89

From the above it can be seen that a macro (primitive or user-defined) is in this text often referenced by its signature. The signature contains both the name of the macro and the number of arguments it takes, separated by the # (octothorpe) character. The octothorpe and ensuing integer are omitted if a macro does not take arguments. A new macro is defined by specifying the required signature (without the leading backslash) as the first argument of one of the definition macros. In this text a signature is usually prefixed with the backslash.

The example above also defines user macros a, b, and c. The \set#2 primitive will not warn when a previous definition exists. The \setx#2 acts similarly but will also first evaluate the value assigned to the macro. Finally, \push#1 and \pop#1 temporarily create a new dictionary in which the definitions are stored. This is one easy way to ensure that no other definitions are overwritten. This level of care is generally not required though.

The following are useful to know about primitives, built-ins and user macros.

Primitives and built-ins live in one namespace (or dictionary), user macros live in another.

A built-in is a special macro provided by zoem. It is defined in terms of one or more primitives, but its definition lives in the same dictionary as primitives do. It is called a built-in because its definition is built into the zoem interpreter. Example: begin#1 is defined as \begin{\1}{} (cf \begin#2). The full list can be obtained by issuing zoem -l alias.

Primitives and built-ins can be shadowed by user-macros, but a warning will be issued. You can test this by issuing e.g. \def{def#2}{\set{\1}{\2}}. This particular piece of code redefines \def#2 as \set#2 by shadowing the primitive \def#2 as a user macro, losing the property of \def#2 that it warns if a key already exists.

Primitives and built-ins can always be accessed by prefixing the name with a right quote, as in \'def{foo}{bar}. The prefixed primitive syntax also has the advantage that it is slightly faster, although zoem speed is likely not something one should worry about.

It is impossible to access a user macro with the quote prefix syntax.

It is probably a good idea in macro packages that export functionality to use the primitive quote prefix syntax. This protects the package from user redefinitions. At the same time, the ability to shadow zoem primitives implies that user macros (also those exported by macro packages themselves) are protected against potential clashes with zoem primitives that may be introduced in later versions of the language. The Fibonacci example looks as follows using the quote prefix syntax.

\'def{fib#1}{ \'push{fibonacci} \'set{a}{1} \'set{b}{1} \'set{c}{0} \'while{\'let{\a <= \1}}{ \'setx{c}{\a} \'setx{a}{\'let{\a + \b}} \'write{-}{txt}{\c\|} \'setx{b}{\c} } \'pop{fibonacci} }

The quote mechanism only works for zoem primitives and built-ins that follow the syntax of user macros. This includes names starting with a dollar $ or with a double quote ". The primitive \$#2 and the built-ins \"" and \""#1 are the only examples in this category. The quote mechanism does not work for special zoem primitives such as data keys ( Tree data ), delay keys (\!#1), or XML syntactic sugar ( SGML/HTML/XML syntactic sugar cubes ).

List of escape sequence classes

This is a list of escape sequence classes recognized by zoem, indexed by the (set of) character(s) triggering the class(es) — this assumes that the character in question is preceded by an active backslash.

$[_a-zA-Z]*

[dollar key] A sequence starting with a dollar sign possibly continued with underscores and alphanumeric characters. Introduces a dollar key. No dollar signs are allowed in the remainder, and the first non-alphanumeric non-underscore character terminates the sequence. The primary use of dollar keys is that they are set by \begin#2 and \end#1. Dollar keys live in the dollar dictionary stack, which is pushed and popped by \begin#2 and \end#1. Nested begin/end scopes can thus safely associate different values with the same key name. Refer also to the Macro expansion section, the The zoem language section, and the Dictionary stacks section.

Note: \$#2 is the only zoem primitive starting with a dollar.

 
[_a-zA-Z][_a-zA-Z0-9]*

[user key/zoem primitive] A sequence starting with an underscore or an alphabetic character, with only underscores and alphanumeric characters in the remainder. Introduces a user key or a zoem primitive. The first non-alphanumeric non-underscore character terminates the sequence. These keys live in the user dictionary stack, which the user can control with the \push#1 and \pop#1 primitives. Refer also to the Macro expansion, The zoem language, and Dictionary stacks sections.

A sequence consisting of a single underscore (i.e. not followed by an alphanumeric character) introduces an anonymous key.

 
"

[user key or zoem built-in] Starts a user key, which is only different from the user keys mentioned above in that it looks different. The sequence is terminated by a closing ". Inbetween, anything is allowed except a backslash or curly. This is used for creating mnemonic names such as

\"man::author" \"man::section" \"man::version" \"html::title" \"html::charset"

These keys live in the user dictionary stack. See the Macro expansion section and the Dictionary stacks section.

There are two zoem built-ins that take this particular form. These are \"" and \""#1. Both expand to nothing. The first can be used to temporarily separate two pieces of text, as they will be joined after expansion. The second can be used to quickly outcomment sections of text.

 
'

[primitive quote prefix] As seen above, primitives and user keys largely live in the same syntactic namespace. It is possible to unambiguously invoke a primitive by inserting a right quote to the left of the primitive key or built-in. Refer to section Primitives, built-ins and user macros .

The user keys live in a stack of dictionaries. Dictionaries can be pushed and popped using \push#1 and \pop#1. The default user dictionary is always present and acts as a global namespace. It is possible to retrieve a key \foo directly from the global namespace using the syntax \''foo, even if it is shadowed in stacked dictionaries. It is possible to set a key in the global namespace using \set#3.

 
%

[data key] A sequence starting with a percent sign. The percent sign is followed by a number of scopes. This is used to access multi-dimensional data storage. Such data is stored using the \def#2 primitive or one of its siblings. Refer also to section  Tree data .

 
[1-9]

[positional parameter] A single (character encoding a) positive digit. The sequence backslash followed by digit is called a positional parameter. It is only interpreted in the second argument of \set#2, \setx#2, \def#2, and \defx#2, and in the definition part of an anonymous key (which can be an argument to \apply#2 and \inspect#4). In all these instances, the sequence denotes a positional parameter into which the corresponding argument will be interpolated when a key with arguments is used. It is allowed in other places though, as it is possible in zoem to create key definitions dynamically (see e.g. the \setx#2 primitive). Note during interpolation, positional parameters that are enclosed by the delay scope \!{..} will not be interpolated (see \!#1). The status of this feature is not entirely clear.

 
<newline>

[strip newline] The newline will be stripped during the interpretation stage. If you want the newline to be stripped during the file-read preprocessing stage use the sequence \:{/}, which is a special case of the comment sequence (see below).

 
:

[preprocessing sequence] There are a few preprocessing sequences, which are evaluated during file read (cf the File read section). The most important preprocessing sequence is simply the sequence \: followed by whitespace, an alphanumeric character, or a backslash. It introduces a comment up till and excluding the next newline, which is stripped.

 
|

[zoem glyph] Comprises a special two-character sequence that can be given a device-specific meaning. It is customarily used to encode a line break. To zoem, this sequence is more or less the same as a 'normal' character. See the \special#1 primitive.

 
~

[zoem glyph] It is customarily used to encode a non-breaking space. See the entry above.

 
-

[zoem glyph] It is customarily used to encode a long dash. See two entries back.

 
\

[backslash] Denotes a literal backslash.

 
{

[left curly] Denotes a literal left curly.

 
}

[right curly] Denotes a literal right curly.

 
*

[glyph sequence] Starts a glyph sequence or constant sequence. Refer to the Device scope section and to the \constant#1 primitive.

 
<

[syntactic sugar] This introduces syntactic sugar for directly writing SGML-style mark-up, such as HTML and XML (e.g. DocBook). Refer to the anchor section for that topic.

 
@

[at scope] Typically seen in macro package files only. Starts a special instance of device scope called at scope. The sequence \@ must immediately be followed by a pair of balanced curlies, so at scope always appears as \@{..}. Refer to the Scope dichotomy and Device scope sections for more information.

 
&

[and scope] Typically seen in macro package files only. May only be used within device scope, and implements a limited form of macro expansion within that scope. The sequence \& must immediately be followed by a pair of balanced curlies. so and scope always appears as \&{..}. Refer to the Scope dichotomy and Device scope sections for more information.

 
`

[back quote - formatting escape] Typically seen in macro package files only. Must be followed by a pair of balanced curlies enclosing a formatting sequence. This is only recognized within the \formatted#1 primitive. This primitive removes all literal whitespace it encounters in its argument; the formatting sequences are transformed to the whitespace characters encoded by them.

 
,

[comma - atomic separator] Typically seen in macro package files only. This is interpreted during filter time, and is always mapped to nothing. Use it for glueing things as in \foo\,1, which will result in theresultoffoo1.

 
!

[delay sequence] Typically seen in macro package files only. Introduces a zoem meta sequence. Such a sequence consists of a maximal run of consecutive backslashes, possibly followed by a single block. It can be used to delay interpretation during any number of interpretation stages, and is useful to delay interpretation, perhaps even in a nested fashion, for arguments in keys such as \apply#2 that expand one or more of their arguments before use. The run of exclamation marks (or 'bangs' as they are internally called) actually comprises an argument to the underlying primitive, so the two primitives (one taking a single block argument) internally have respective signatures !#1 and !#2. Externally though, they are just refered to as \! and \!#1.

 
=

[inline files] Rarely used feature. Starts either a sequence of the form \={fname}, which begins a so called inline file named fname, or a sequence of the form \==, which ends such an inline file. Refer to the File read section.

This leaves 0>()[]?^#/.; for future use, hopefully very few of these will ever acquire meaning. If the sequence \# acquires meaning, it will probably be for encoding Unicode scalar values.

Parsing stages

Parsing is separated into three stages, conceptually. Zoem knows two different parse scopes, plain scope and device scope. These are mentioned below, and explained in the Scope dichotomy section. The three stages are:

File read
Macro expansion / file inclusion - only plain scope is seen.
Filtering - both plain scope and device scope are filtered. Device directives that lay hidden in device scope are interpreted during output.

A file is read in chunks, if possible. The requirement is that chunks must end on lines and be in the outermost scope. The default minimum chunk size is approximately one megabyte. Chunks are processed by recursively chunking them into smaller chunks as dictated by macro expansion. As soon as a chunk is no longer subject to macro expansion it is immediately filtered and output.

Macro expansion is done recursively. Whenever a macro is encountered, it is replaced by its expansion, and the result is again fed to the parser. Evaluatation is not necessarily lazy, that is, during macro expansion the expander may expand arguments before they are interpolated and substituted in the macro definition. This inside-out evaluation can recurse if necessary. Many zoem primitives evaluate one or more of their arguments before use. The default behaviour for user macros is lazy evaluation. This can be changed however by wrapping both the macro and its arguments in \apply#2. Expansion can be delayed using \! and \!#1, so different arguments can be treated differently.

Important is that the result from the second stage is still valid zoem input. If you re-feed it to zoem, file read and macro expansion are usually no-ops (unless some interpretation delay-magic was used), and the syntax is garantueed to be acceptable to zoem. This is because device scope is not touched during the first two stages, and device specific text (which is most likely not conforming to zoem syntax) lies always hidden in that scope. There are three kinds of escape sequences introducing device scope; these are described in the Device scope section.

This is used for example when creating a table of contents; you can write expanded but unfiltered content to a file and read it in during the following run. It is important that such content is fully expanded, because you want things like index numbers and references as they are at the time of macro invocation. It is equally important that what you read back in is still valid zoem input; this is simply achieved by witholding filtering. When the table of contents is read in, it can be subjected to filtering, and this is the right way to do toc stuff in Zoem.

File read

File read - stripping comments, reading inline files.

Zoem searches for files included via \dofile#2 or one of its built-in aliases in a number of places if it cannot find the file in the current directory. The precise way of searching is documented in section File search path .

\:

In most cases, this sequence introduces a comment, namely where it is followed by whitespace, an alphanumeric character, or a backslash. It introduces a comment up until and excluding the next newline, which is stripped.

The sequence \:{/} introduces a comment up till and including the newline. This feature can be useful within the \protect#1 primitive, as it is the only way to delete actual newlines within the argument of that primitive.

The sequence \:{!} is replaced by a backslash. The single use currently known is to make it easy to quote zoem input containing comment sequences. This

\protect{\foo \bar \zut \:{!}: this will end up as a comment. }

will result in the following

\foo \bar \zut \: this will end up as a comment.
 
\={fname}

starts inline file named fname at the next line, removes remainder of line after the \={fname} sequence. When using the \dofile#2 primitive or one of its four built-in aliases, an inline file takes precedence over regular files in the file system, whether it is present (as a regular file) or not. See below. This feature can be used to ship zoem input in one piece while putting the macro parts at the end. \zinsert#1 can address inline files as well, but \finsert#1 cannot. The reason for this is that inline files have to satisfy zoem syntax, whereas \finsert#1 can be used to read arbitrary data.

The future will probably bring a zoem option that creates such a self-contained file automatically from the zoem entry file.

 
\==

ends inline file, removes remainder of line.

The above applies to any file read at any stage. Inline files may occur in any file included at any time, but they do not nest.

The zoem entry file is the single file that is specified on the command line. This is the main file, from which other files can be included if desired.

Zoem entry files usually have the extension .azm, which is memnonic for A ZoeM file. This is required if the -i option is used. Arbitrary entry file names can be specified using the -I option. It is not uncommon to generate sibling files with .roff, .html, .zmt (zoem table of contents), and .zmr (zoem references) extensions — however, this is all configurable in user space and not part of zoem itself. There are no restrictions on names of files that are included from the entry file. Inclusion is done recursively.

The future will probably bring a second extension that is allowed, namely .ezm for Expanded ZoeM file, which is a self-contained file in which every included file is present as an inline file.

File search path

If zoem cannot find a file in the current directory, it attempts to find the file in one of three different ways. These are, in the order in which they are attempted:

The environment variable $ZOEMSEARCHPATH is checked. It may contain a listing of paths separated by whitespace or colons.

The zoem variable \__searchpath__ is checked. It must contain a listing of paths stored as a vararg, i.e. a sequence of paths where each path is delimited by curly brackets. DO NOT overwrite this variable, but rather append or prepend to it. Most likely zoem was configured and compiled locally on your system, in which case \__searchpath__ contains the path necessary to find the macro packages man.zmm, faq.zmm, and ref.zmm.

The path of the file currently being parsed is used. Assume that file foo contains \import{/a/b/c/bar}. If file bar wants to include file zut, which is in the same /a/b/c/ directory, it need not prepend a path but can just issue \import{zut}. Should the previous search mechanisms fail to find zut, then zoem will as a last resort deduce the path from /a/b/c/bar. This feature is probably rarely needed, if ever at all.

Macro expansion

Macro expansion consists of recursive file inclusion and macro expansion. All zoem primitives and user keys are recursively expanded until none remains. Zoem primitives and user keys take one of the following forms:

\abc_0123_

A key with alphanumerics and underscores only. Ends with any other character. All zoem primitives but one have this form.

Note: \_ denotes an anonymous key, see the Anonymous keys section.

These keys live in the user dictionary stack. Initially, there is only one dictionary. The stack can be manipulated using the \push#1 and \pop#1 primitives.

 
\"abc::def-ghi.jkl,mno+qrs"

A quoted key. Almost anything inbetween quotes is allowed. Always ends with a quote. No zoem primitive has this form. These keys live in the same user dictionary stack as the keys above.

 
\$abc_0123_

A key introduced with a dollar sign. The name may further consist of alphanumerics and underscores and it ends with any other character. These keys live in the dollar dictionary stack. A dictionary is pushed with every occurrence of \begin#2, and that dictionary is popped with the corresponding occurrence of \end#1.

Further note: \$#2 is a zoem primitive.

All three types of keys may take arguments, and overloading is allowed:

\foo \: signature foo \foo{bar} \: signature foo#1 \foo{bar}{bop} \: signature foo#2 \$foo{bar}{baz} \: signature $foo#2 \"foo::oof"{zut}{zit}{zot} \: signature "foo::oof"#3

is an ensemble of valid and unique keys, which can be defined for example by

\def{foo}{FOO} \def{foo#1}{The FOO of \1} \def{foo#2}{The FOO of \1 and \2} \def{$foo#2}{The $FOO of \1 and \2} \def{"foo::oof"#3}{\foo{\1}{\2}\foo{\2}{\3}}

Additionally, zoem allows the definition of constant keys that map directly into device space and are ignored during macro expansion. Usage of such keys looks like \*{'e} or \*{(c)} and is detailed later on.

A sequence \k where k is in 1-9 is allowed within anonymous keys (as used for example in \apply#2 and \inspect#4) and in the definition argument of the \def#2 primitive and its siblings \defx#2, \set#2, and \setx#2. It indicates the position(s) where arguments should be interpolated. Note during interpolation, positional parameters that are enclosed by the delay scope \!{..} will not be interpolated (see \!#1). The status of this feature is not entirely clear.

A feature that should only rarely be needed is that zoem allows name scopes. Refer to the Dictionary stacks section.

File inclusion

There is one zoem primitive which has four different uses. For each of those uses, a built-in alias exists.

\dofile#2 use alias meaning \dofile{expr}{!+} \input{expr} require file, interpret and output \dofile{expr}{!-} \import{expr} require file, interpret only \dofile{expr}{?+} \read{expr} permit absence, interpret and output \dofile{expr}{?-} \load{expr} permit absence, interpret only

The \dofile#2 primitive and its four aliases are perhaps a little funny interface-wise — better ideas are welcome. The expr argument is digested, that is, expanded until no macro's remain. It is thus possible to specify \__fnbase__.zmt and include a table of contents file that has been written to in a previous run. \dofile#2 and its aliases have the property that zoem really descends into the files, and on error will emit a message containing the approximate line number where it occurred.

Additionally, the contents of a file can be placed inline using \finsert#1 and \zinsert#1.

Note: wherever key is written, it means that something of the form \foo, \$foo, or \"foo" has to be provided, so you would use \setx#2 e.g. as \setx{foo}{\finsert{\__fnbase__.zyx}}.

Protection

The \dofile#2 primitive requires that the files to be included satisfy zoem syntax. It will descend into the files and proceed parsing them.

The \finsert#1 and \zinsert#1 primitives do not descend, but rather act as if the contents of the file specified were pasted into the place of macro invocation.

\finsert#1 will protect the contents of the inserted file, that is, all backslashes and curlies are escaped by preprending them with a backslash. \zinsert#1 will include the file unchanged, assuming that its contents satisfy zoem syntax.

The \system#3 primitive is able to pipe data to a system command's STDIN stream and retrieve data from the command's STDOUT stream. This primitive will unprotect the data it sends, and it will protect the data it receives. Note the security implications of this feature as discussed at the \system#3 entry.

Data can be explicitly protected using the \protect#1 primitive.

Protected data can (currently) never result in it being expanded again. This is because escaped backslashes are only interpreted at filter time, and never during expansion. If you only need temporary delay of expansion, use the \! primitive or the \!#1 primitive.

Scope dichotomy

Zoem knows two parse scopes: plain scope and device scope. The latter is also called 'at scope' because \@{..} is one (but not the only) way of entering device scope. In plain scope, every character represents itself as a glyph, i.e. as something that should show that way in print/on screen (after the zoem output/device input is fed to the device interpreter).

For example, if you write the less than sign < in plain scope, it should show up as a readable less than glyph, like in this very sentence. In order to make this happen, zoem provides the \special#1 primitive, so that the less than sign can be automatically mapped to the html entity sequence &lt;.

In device scope, nothing is mapped except for a double backslash should it occur. If you enter this particular sequence of mixed scope: \@{<b>}<hello world>\@{</b>} as zoem input, the zoem output/device input is (provided the \special#1 primitive was correctly used for the html device): <b>&lt;hello world&gt;</b> and what you finally see on screen is: <hello world>. In device scope, every character (except for the escape sequences available in that scope) represents itself as the character that should be present in the zoem output/device input. Device scope should normally only be seen in macros and not in running zoem input.

In plain space you type characters just as you want to see them eventually — when you read the document after the zoem output was run through a device interpreter (such as a browser or printer, or postscript previewer). The only exceptions are the backslash and the two curlies, these should be entered as \}, \{, and \}, respectively. Those escape sequences are interpreted as the characters or glyphs \, {, and }. For all characters, including these three, it is checked whether they should be further mapped according to the \special#1 primitive. If a mapping is found, it is retrieved and interpreted by the device scope filter. Read on.

Device scope

There are three kind of strings which are interpreted by the generic device filter, and which are said to live in device scope:

The strings embedded in \@{..} sequences.

The strings mapped to by the \special#1 primitive, including mappings of the zoem glyphs \~, \|, and \-.

The strings mapped to by the \constant#1 primitive.

In a macro package that is meant to work for multiple devices, every use of any of these constructs will typically be embedded in something that tests the value of the active device. This can be done using either \cmp#3 with \if#3, \switch#1, or \$#2, in conjuction with the pre-defined zoem key \__device__, containing the name of the active device (which can be specified on the command-line). The following are equivalent:

\if{\cmp{eq}{\__device__}{html}}{ \@{<!-- (c) foo bar -->} }{} \: is equivalent with \${html}{ \@{<!-- (c) foo bar -->} }

The \$#2 primitive is used if something needs to be done for one device only, and it may occasionally appear in documents. For example, the PUD man macros enable the creation of a table of contents (for both html and troff). My own convention is to have a table of contents only in html, and I specify this using the sequence

\${html}{\"man::maketoc"}

When zoem enters device scope, it outputs all characters literally, except that the backslash still has special meaning. It is used for encoding the backlash itself (as \\), and for encoding the two curlies { and } (as \{ and \}). This is the same as in plain scope (except that in plain scope the resulting character may again be mapped onto something else, for example, in troff the backslash also needs encoding as \\).

In device scope the sequence \" maps to a double quote. This is an additional feature to allow zoem input to be more susceptible to some editors moving features. It is not necessary though; simply using the double quote without escaping it is sufficient.

Additionally, the backslash can be followed by a single letter from a prescribed set listed below. Such a backslash+letter combination is called a device directive. By default, zoem will never print consecutive newlines, and it will never print consecutive spaces or spaces at the beginning of a line. The device directives allow this to be altered.

N

garantuee a newline

P

garantuee a paragraph skip (two consecutive newlines)

S

garantuee a space (except if next char is newline)

I

increase indent by one (indent is printed after each newline)

J

decrease indent by one

C

set indent to zero

n

print newline

s

print space

t

print tab

w

stop managing white space (squashing spaces and newlines)

W

start managing white space (use after w)

&

start and scope (see further below)

+

set the special level (see further below)

Note that the directives mainly affect the lay-out of the device text (which is zoem output), not the look of the interpreted device text. The 'N' directive is rather important when constructing troff macros, as many special troff commands are encoded by a dot as the first character on a line, i.e. a newline followed by a dot. Since troff attaches special meaning to two consecutive newlines as well (interpreting it as a paragraph break), zoem needs to be able to specify print a newline only if the previous character was not a newline. This is exactly what the N directive means. The 'W' and 'w' directives are required for enabling the construction of a verbatim environment.

The sequence \&{<almost any>} can be used to avoid overly cumbersome constructions. It is for example illegal to write

\@{<table width="\width">}

In the early days of zoem, you had to write

\@{<table width="}\width\@{">}

— ugly by most standards. Today you write

\@{<table width="\&{\width}">}

Which is not any shorter, but more pleasant to read. What happens is that the contents of and scope \&{..} is first fully expanded in plain scope, after which the result is passed back to device scope. You have to be careful though. The content of \&{..} should never expand to something containing the at sequence \@{..}, because device scope is not allowed to nest. It should also not expand to something containing the and sequence \&{..} either, as this sequence is illegal in plain scope.

Device scope resulting from mapping special characters

The first kind of zoem escape introducing device scope is \@{..}. The second kind comprises the \special#1 mappings, including the three zoem glyphs \~, \|, and \-. Conventionally, these are used to encode a non-breaking space (&nbsp; in html), a line break (<br> in html), and a long dash (emdash, not present in html). You would for example put

\if{\cmp{eq}{\__device__}{html}}{ \special{ {38} {&amp;} \: 38 is ascii character '&' {60} {&lt;} \: 60 -> '<' {62} {&gt;} \: 62 -> '>' {-1} {&nbsp;} \: the zoem escape \~ {-2} {<br>\!N} \: the zoem escape \| {-3} {-} \: the zoem escape \- } }{ }

All \special#1 definitions are interpreted in device scope. For every character encountered in plain scope, it is checked whether a \special#1 definition exists, if so, the corresponding string is retrieved and this is filtered through the device scope filter. Note that the three zoem glyphs described here may not be used in device scope, they can only be used in plain scope. In device scope you will have to write the explicit, device-specific sequence such as <br> (in html).

The \special#1 primitive allows different levels of mappings to be defined simultaneously. Several definitions of the same character are allowed; these are placed on a stack particular to that character (cf. the \special#1 entry). When zoem encounters a character for which one or more mappings exist, it retrieves a mapping using the special level. This is an integer that has by default the value 1. Each open output stream has a unique special level associated with it. [Output streams exist for the default output file (see e.g. \writeto#1) and for each file openend by \write#3]. A mapping is retrieved using this rule: The deepest element is fetched for which the depth does not exceed the level. The most visible element (which is the element first occurring in the \special#1 invocation) has depth 1.

The presence of different levels comes in handy e.g. when the troff device is used. In some contexts, the double quote is a special character in troff (and a printable quote is then mysteriously represented by two consecutive double quotes), in most contexts it is not. This is combatted by including these two specifications in the \special#1 call preparing for troff output (note that 34 is the ASCII value representing the double quote):

\special{ ... {34}{"} {34}{""} {92}{\\e} ... }

The first pair shown simply maps the double quote onto itself, and the second pair maps it onto a double double quote. As long as the special level is 1, the second definition is not used. The backslash (with ASCII value 92) needs only one definition as it is escaped in the same way in all troff contexts.

The special level can be set using the \+ directive, which must be followed immediately by a digit in the range 0-9 enclosed by curly brackets, e.g. \@{\+{2}} will set the special level to 2. The special level can be set to 0 (zero) and this means that no character will be mapped.

Example
Double quotes need to be escaped in certain troff contexts. This is achieved by the following.

\@{\+{2}"} ... funny quote context ... \@{"\+{1}}

Such a context is typically encapsulated by a macro defined in a package; its definition should never be visibile to the user of the package. Note that the double quotes embedded in at scope in the example above are not susceptible to special mapping — mapping is only applied in plain scope.

Device scope resulting from glyph definitions

The third kind of device scope strings are those mapped to by the \constant#1 primitive. An example of (toy) usage is this:

\constant{ {'e} {&eacute;} \: Use e.g. as \*{'e}l\*{`e}ve (élève) {(c)} {&copy;} \: Use e.g. as \*{(c)} DEEDEE (© DEEDEE) {+-} {&plusmn;} \: Use e.g. as \*{+-} a few (± a few) }

This is largely convenient syntactic sugar. These constants could also have been defined as

\def{"'e"}{\@{&eacute;}} \def{"(c)"}{\@{&copy;}} \def{"+-"}{\@{&plusmn;}}

The idea is that the \*{..} namespace is used for glyph-like device-specific bindings, whereas the \".." namespace is used for semantic purposes that are device-independent, but nothing prohibits you from fiddling with this.

SGML/HTML/XML syntactic sugar cubes

Zoem provides a shorthand for entering SGML-style tags. It is checked by zoem for well-formedness of the resulting SGML code, and it can be freely mixed with other modes of entering tags. Normally you would have to enter SGML-style tags in device scope, or write a macro for doing that. For example, a macro x#2 that expands \x{b}{be bold} to \@{<b>}be bold\@{</b>} is a likely candidate. However, this would be inelegant for constructions that span a long distance, and it does not provide for letting zoem expressions expand within an xml tag.

Zoem provides the \< token. It can be used in several ways:

\<foo> \: foo can be an expression. Some <content> \: of course, expressions may occur here as well. over here. \<bar>{zut} \: bar can be an expression too; \: this syntax will close itself. Some <content> \: again, expressions may occur here as well. over there. \<> \: this is a closing tag for the first foo. \</foo> works too. \<tim x=y/> \: zoem knows this closes itself. \<*br> \: zoem converts this to <br>

Suppose that foo, bar, and zut are zoem expressions expanding to strings FOO, BAR, and ZUT respectively (FOO and BAR might be of the form tag a="b" c="d"). Provided that the characters <, >, and & are automatically mapped in plain scope (as a result of correct \special#1 usage), the above will result in

<FOO> Some &lt;content&gt; over here. <BAR> ZUT </BAR> Some &lt;content&gt; over there. </FOO> <tim x=y/> <br>

The foo part inside the \<foo> syntax should never expand to something containing a >. This is entirely the responsibility of the user or macro package author.

Both kinds of syntax, \<foo> and \<bar>{zut}, are kept as they are during the expansion stage, and they can be subjected to multiple levels of expansion (which may be the case if such syntax is used inside e.g. \setx#2 or \apply#2). It is only at the output stage that the syntax is transformed to actual SGML code and that well-formedness is checked. So, the two examples just seen will first transform to \<FOO> and \<BAR>{ZUT} (please note that foo, bar, and zut all denote expressions here). If they are at that point no longer subject to expansion they enter the output stage where they are converted to <FOO> and <BAR>ZUT</BAR> (plus some additional formatting/indenting) respectively.

Zoem pushes on a stack of opening tags whenever it encounters \<foo> syntax during the output stage. It naturally knows that a tag can be followed by attributes. It also knows that a tag such as \<tag a=b/> closes itself (XML syntax), and the applies for DTD tags such as \<!ENTITY ...>. As a special case, \<*tag foo bar zut> is converted to <tag foo bar zut> to allow encoding of HTML tags such as <meta>, <link>, and <hr>. This syntax is mandatory for tags that will not be closed. Note that you should only use \<p> if you are going to use \</p> or \<> as well (because zoem requires closing tags for opening tags). That said, the syntax \<p>{ paragraph content } is preferable in most cases.

Zoem does not know about other ways of entering tags, so \@{<body>} would not affect the stack just mentioned. \<> automatically closes the top level opening tag from the stack. Again, syntax such as \@{</body>} does not interact with the stack.

It is possible to explicitly close a tag by simply using \</foo> syntax. Zoem will check whether the closing tag matches the top level opening tag. As seen before, \<> does the same thing, but rather than doing a check, zoem will use the top level opening tag to construct the corresponding closing tag.

Zoem miscellanea
Key signatures

Several keys take another key as argument, e.g. they store a value in a second key or check whether the second key exists. The full list of these meta keys is \def#2, \defx#2, \set#2, \setx#2, \undef#1, \defined#2, \apply#2, and \inspect#4. In all cases, the argument key is passed as the first argument, by means of the key signature.

For a key \key taking k (k>0) arguments its signature is key#k. The signature of a key \key taking no arguments is simply key. The rule is: Key usage always includes a single leading backslash (this activates the key). When a key is subject of inspection, it is always referred to by its signature.

Throughout this text, a key with signature key#k is mentioned by means of its key mention \key#k, that is, for extra clarity the backslash is prepended to the signature.

As explained in Primitives, built-ins and user macros, almost all primitives can be specified using quote syntax. The quote syntax is integrated with signatures. This means that primitives that expect a signature (such as \def#2, \undef#1, and \apply#2) accept quoted signatures too when the signature refers to a primitive.

Anonymous keys

A single underscore introduces an anonymous key. It is optionally followed by a #k tag (for k in 1..9), denoting the number of arguments the anonymous key takes. An occurrence of the latter is called a tagged anonymous key. The first argument to the key should be a key definition, the other arguments are the arguments for that key definition. If a tag is present, it is used for verifying that the anonymous key is used properly.

\_{\1 the \2}{row}{boat} \_#2{\1 the \2}{row}{boat}

results in

row the boat row the boat

Anonymous keys may occur in the first argument of \apply#2, within the first argument of \inspect#4, and they may occur freely in running text. The presence of a tag is required when an anonymous key is used within either of \apply#2 and \inspect#4. An example of usage in \apply#2:

\apply{_#2{\1 kisses \2\|}}{{bill}{max}{max}{bill}} bill kisses max max kisses bill

or even

\set{%foo}{{{\1 hugs \2\|}}} \apply{_#2\%{foo}}{{bill}{max}{max}{bill}} bill hugs max max hugs bill

Note that in order to store a block with \set#2, an extra pair of curlies has to be used, as blocks can only be passed as a sub-argument of a single-element vararg. Also note that in a vararg it is allowed to put white space inbetween the constituting elements.

Tree data

Data can be organized in a global tree with a specialized use of \set#2 and its siblings, as shown further below. The data is retrieved from the tree using so called data keys. Such a key is started using a percent sign, immediately followed by zero, one, or more blocks, e.g. \%, \%{..}, and \%{...}{...}{...} would all be allowable invocations. If more than one block follows the percent sign, there must be no interleaving white space.

The underlying primitive has signature %#1, as the trailing scopes are congregated into a single argument before they are further processed. The two sibling primitives %free#1 and %dump#1 serve for freeing and dumping parts or whole of the tree, as described further below.

When applied to data keys, \set#2 and its siblings set one or more values in a global multi-dimensional associative array that we shall refer to here as ROOT. Please note that ROOT is for explanatory purposes only. This associative array is best viewed as a tree, in which every node can have branches to higher nodes. A node may or may not contain a value. Let us denote the value contained by a node some-node as *(some-node). The fact that beta is a node one branch higher than alpha, which is in turn one branch higher than ROOT, is denoted as ROOT->"alpha"->"beta". In this path notation, strings indexing nodes in the trees are written inbetween quotes. This has the advantage that the empty string, which is a valid index string, has the representation "". Combining these conventions, we write the value associated with beta as *(ROOT->"alpha"->"beta"). Consider these examples.

\set{%{foo}{bar}{zut}}{lez} \: now *(ROOT->"foo"->"bar"->"zut") is "lez" \set{%{foo}{bar}{zut}}{{a}{b}{x}{y}} \: now *(ROOT->"foo"->"bar"->"zut"->"a") is "b" \: and *(ROOT->"foo"->"bar"->"zut"->"x") is "y" \: and *(ROOT->"foo"->"bar"->"zut") still is "lez" \: some special cases \set{%{foo}{bar}{zut}}{{{c}}} \: now *(ROOT->"foo"->"bar"->"zut") is "{c}" \set{%{foo}{bar}{zut}}{{c}} \: now *(ROOT->"foo"->"bar"->"zut") is "c" \set{%{foo}{bar}{zut}}{c} \: now *(ROOT->"foo"->"bar"->"zut") is "c" \set{{foo}{bar}{zut}}{{c}{d}{e}} \: This does nothing, because the second argument \: must either be an *even* vararg, a 1-element vararg, \: or a simple argument. \set{%{{tiger}}}{in the woods} \: now *(ROOT->"{tiger}") is "in the woods" \set{%{tiger}}{in the woods} \: now *(ROOT->"tiger") is "in the woods" \set{%tiger}{on the loose} \: now *(ROOT->"tiger") is "on the loose" \: stripping curlies from a vararg with one argument \: does not make a difference with the exception of \: the case shown below. \set{%{}}{empty} \: now *(ROOT->"") is "empty". \set{%}{root} \: now *(ROOT) is "root".

Take note of the rule governing the second argument. If the first non-white space character is a left curly, \set#2 expects a vararg. The vararg must either be even or it must contain exactly one argument.

An even vararg is interpreted as a sequence of key-value pairs. Each key induces a new branch from the node specified in the first argument, and each value is associated with the node at the end of that branch. If the vararg contains exactly one argument, that argument is simply used as a value. This is the only way to specify a block as the value. If the first non-white space character is not a curly, \set#2 will simply interpret the second argument as a value to append to the node specified in the first argument. It is possible to sidestep these issues by using \set#3 and the directive u as argument to the modes key. This will cause the value to be copied without further interpretation as a vararg or block.

If you want the data to be stored to be expanded before it is bound, use \setx#2 or \defx#2.

Data is retrieved simply by prefixing the path with the \% token. Example:

\set{%{foo}{bar}{zut}}{{a}{b}{x}{y}} \%{foo}{bar}{zut}{a} \%{foo}{bar}{zut}{x}

will print b and y. If the path is not an existing path in the current tree it will simply be ignored, although an error message will be emitted.

Whole or part of the data tree can be freed using the \%free primitive. Again, simply append the access sequence in which you are interested. For freeing the entire tree, use \%free without trailing scopes. The \%free primitive largely exists for testing purposes to ensure that zoem gets its internal data manipulation right.

Whole or part of the data tree can be output for debugging purposes using the \%dump primitive. Simply append the access sequence in which you are interested. For printing the entire tree, use \%dump without trailing scopes. This can be used for debugging if your data manipulation does not work out as expected. There is no result text as far as usual processing is concerned. The underlying primitive dumps its findings to STDOUT in a line-based textual representation of the data-tree.

Of blocks and varargs

A block is a string beginning with a left curly and ending with a right curly, the curlies being balanced. This is a convenient naming convention. Blocks can be used in constructing anonymous keys; refer to the Anonymous keys section.

Some keys take a vararg argument, which is a single argument (enclosed by curlies as are all arguments), which can contain any number of sub-arguments, that is, a list consisting of blocks. Inbetween the blocks white space may occur. The \special#1 and \constant#1 keys both take a single vararg argument, and the \apply#2 and \switch#2 keys each take a vararg as their second argument. For \apply#2 the first argument is a key that is applied to subsequent batches of arguments from that vararg. The \table#5 primitive takes a vararg as its last argument. For examples, see the A zoem tour section and the \apply#2 entry.

An even vararg is a vararg with an even number of elements, An odd vararg is a vararg with an odd number of elements.

User keys may check whether an argument is a vararg by employing the \nargs#1 primitve. This can be used to take different actions depending on the structure of the argument.

Session keys

This is a compact listing of session keys, created by issuing zoem -l session.

Predefined session variables \$__args__ (local to env) key/value pairs given to \begin#2 \$__xargs__ (local to env) key/value pairs given to \begin#2, expanded \__device__ name of device (given by -d) \__fnbase__ base name of entry file (given by -i/-I) \__fnentry__ name of entry file (given by -i/-I) \__fnin__ name of current input file \__fnout__ name of current output file \__fnpath__ path component of entry file (given by -i/-I) \__fnwrite__ arg1 to \write#3, accessible in arg3 scope \__lc__ expands to a left curly (only for magic) \__line__ index of current input line \__parmode__ paragraph slurping mode for interactive sessions \__rc__ expands to a right curly (only for magic) \__searchpath__ search path for macro packages (e.g. man.zmm) \__split__ user space toggle for chapter mode indicator \__sysval__ exit status of last system command \__version__ version of zoem, formatted as e.g. 2003, 2004-010 \__zoemput__ result text of last \try#1 key \__zoemstat__ status of last \try#1 key

This manual is littered with examples of the usage of \__device__. The \__fnbase__ key is useful for creating sibling files of the entry file, i.e. a table of contents file or a file containing reference information. I have the habit of naming those \__fnbase__.zmt and \__fnbase__.zmr, respectively. The \__fnin__ key is useful for emitting log, warning, or error messages particular to the file currently being parsed. The \__parmode__ macro affects the way in which zoem reads chunks in interactive mode (refer to Section  Invoking zoem from the command line ). The \__searchpath__ macro is one of the ways in which zoem can be instructed to search for files in a set of locations, when confronted with \dofile#2 or one of its built-in aliases. Section  File search path has more information about the mechanism of file location. See also the zoem manual.

Built-in macros

This is the result from doing zoem -l builtin:

Built-in aliases done maps to \'throw{done} ifdef#3 maps to \'if{\defined{\1}{\2}}{\3}{} ifdef#4 maps to \'if{\defined{\1}{\2}}{\3}{\4} input#1 maps to \'dofile{\1}{!+} import#1 maps to \'dofile{\1}{!-} read#1 maps to \'dofile{\1}{?+} load#1 maps to \'dofile{\1}{?-} begin#1 maps to \'begin{\1}{} env#3 maps to \'env{\1}{}{\2}{\3} system#2 maps to \'system{\1}{\2}{} system#1 maps to \'system{\1}{}{} throw#1 maps to \'throw{\1}{} inform#1 maps to \'write{stderr}{device}{\1\@{\N}} append#2 maps to \'set{{modes}{a}}{\1}{\2} appendx#2 maps to \'set{{modes}{ax}}{\1}{\2} seq#4 maps to \'set{\1}{\2}\'while{\'let{\'get{''}{\1}<\3}}{\4\'setx{\1}{\'let{\'get{''}{\1}+1}}} update#2 maps to \'set{{modes}{e}}{\1}{\2} updatex#2 maps to \'set{{modes}{ex}}{\1}{\2} "" maps to (nothing) ""#1 maps to (nothing) group#1 maps to \1 PI maps to 3.1415926536 E maps to 2.71828182846 $#1 maps to \'switch{\__device__}{\1} $#3 maps to \'switch{\__device__}{{\1}{\2}{\3}}
Dictionary stacks

By default, when using \def#2 and \set#2, keys and their values are put in a global user dictionary. It could be useful to shadow keys by entering a new name scope. Zoem facilitates this by providing the \push#1 and \pop#1 keys. These push and pop a new dictionary onto/from the user dictionary stack.

A second dictionary stack is the dollar dictionary stack, which contains all keys that start with a dollar sign. The \begin#2 primitive pushes a dollar dictionary each time it is invoked, and that dictionary is popped by the corresponding \end#1 invocation. This is typically useful for creating nested environments that need access to the same type of information - by storing such information in dollar keys, it can be shadowed and recovered. Refer to the \begin#2 entry.

When a key is used its definition is searched in all dictionaries, starting from the top-level dictionary. The key \undef#1 has only access to the top-level dictionary, and will never delete a key in any other dictionary.

A zoem tour

What follows is an informal tour through zoem's offerings. The next section contains a comprehensive overview of the zoem primitives.

Let us start with how filtering in plain space is configured. The following was obtained from the PUD man macros.

\switch{\__device__}{ {html}{ \special{ {38} {&amp;} {60} {&lt;} {62} {&gt;} {-1} {&nbsp;} \: the zoem escape \~ {-2} {<br>\!N} \: the zoem escape \| {-3} {-} \: the zoem escape \- } } {roff}{ \special{ {46} {\\.} {96} {\\`} {92} {\\\\} \: a single backslash {-1} {\\ } \: the zoem escape \~ {-2} {\!N.br\!N} \: the zoem escape \| {-3} {\\-} \: the zoem escape \- } } {\write{stderr}{txt}{No such device: \__device__\|} \write{\__fnbase__.err}{txt}{No such device: \__device__\|} \exit } }

Take note of the number of backslashes. In order to print a backslash in troff, the troff input must contain two consecutive backslashes. In order to specify a backslash in zoem, we must also provide two, thus we need four backslashes in all (in order to create this example I needed eight backslashes in the zoem input).

Also note the use of the \switch#2 primitive, which takes an expression in the first argument and an arbitrary number of pairs plus an optional clause in the second argument. The optional clause was in this case used as a failure test.

\special#1 is an example of a zoem key taking an argument that may contain arbitrarily many sub-arguments (i.e. a vararg). In this particular case the sub-arguments must be paired, each pair defining how certain characters that are special to the device must be represented.

The \write#3 and \exit need little comment, they work as expected. Zoem opens output files as needed, and closes them when it is done. The file name - is equivalent to either STDOUT or STDIN (depending on context), the file name stderr denotes STDERR.

\exit is considered a failure (and will cause zoem to stop and complain), but \throw{done} is not. \throw#2 with argument done will merely quit parsing the current stack, so if you specify it at top level in a file — not nested in a key that does its own parsing such as \setx#2, zoem will stop parsing the current file and transfer control back to the file from which it was included.

The previous example introduces the keys \__device__ and \__fnbase__. They are so called session variables described in section Session keys.

A sibling primitive to \special#1 is \constant#1. The following is an example of use.

\constant{ {'e} {&eacute;} \: Use e.g. as \*{'e}l\*{`e}ve (élève) {(c)} {&copy;} \: Use e.g. as \*{(c)} DEEDEE (© DEEDEE) {+-} {&plusmn;} \: Use e.g. as \*{+-} a few (± a few) }

The main thing to note here is that the target string (e.g. &eacute;) is always interpreted in device space. In the reference string (e.g. 'e, (c) and +- in the example above) almost anything is allowed, including backslash-escaped characters and balanced curlies. The latter are not recommended though.

There are three zoem tokens representing the characters that have meaning to zoem syntax, the backslash and the two curlies. Those zoem tokens are just like any other plain characters: they can be mapped in plain space, and they are printed literally in device space.

\\ \: A backslash; possibly mapped in plain space. \{ \: A curly; possibly mapped in plain space. \} \: A curly; possibly mapped in plain space. \, \: The atomic separator (vanishes).

These tokens are mapped only during the (final) filter stage. The atomic separator can be useful when you want to glue together items some of which will be the result of macro expansion.

\def{foo}{bar} \foo\,1 \: \foo1 would be the key \foo1

This will result in bar1. The tokens \\, \{, and \} are really the corresponding ordinary characters. They can be mapped in plain space via \special#1 using their ASCII values 92, 123, and 125 as was seen above for the backslash. In device space, they will result in \, {, and }.

Let us now continue with device scope by implementing a \bf#1 key. Below you find two possible definitions:

\def{bf}{1}{\@{<b>} \1 \@{</b>}} \: OK \def{bf}{1}{\@{<b> \1 </b>}} \: Wrong! Wrong!

The second is wrong because the contents of \1 end up in device space. If the expansion of \1 still contains keys they will not be expanded (and cause a fatal syntax error when device space is filtered), and additionally any special characters in \1 will not be mapped.

The zoem language
Alphabetic index
\! \!#1 \$#2 \apply#2 \begin#2 \catch#2 \cmp#3 \constant#1 \def#2 \defx#2 \defined#2 \dofile#2 \dowhile#2 \__env__#1 \end#1 \env#4 \eqt#3 \branch#1 \eval#1 \exit \f#2 \f#3 \fv#2 \finsert#1 \format#2 \formatted#1 \get#2 \if#3 \inspect#4 \length#1 \let#1 \nargs#1 \pop#1 \protect#1 \push#1 \register#2 \set#2 \setx#2 \set#3 \special#1 \switch#2 \system#3 \table#5 \textmap#2 \throw#2 \tr#2 \trace#1 \try#1 \undef#1 \vanish#1 \while#2 \whilst#2 \write#3 \writeto#1 \zinsert#1
Topic index

This is an overlapping categorization in topics.

Using and inspecting keys
\apply#2 \constant#1 \def#2 \defined#2 \defx#2 \inspect#4 \pop#1 \push#1 \set#2 \setx#2 \table#5 \undef#1

These primitives affect or use either user keys that are stored in the user dictionary, dollar keys that are stored in the dollar dictionary, or anonymous keys. Dictionaries are discussed in Section 6.7.

 
Control, booleans, testing and comparison
 
Expansion, delay
 
Meta-zoem, introspection, exceptions, errors
 
Execution, tracing
 
Input/output
 
Filtering
 
Environment scopes
 
Name scopes
 
Data storage
\%, \%free, and \%dump are primitives described elsewhere — refer to the Tree data section.
 
String conversions
 
Arithmetic
 
Glyphs
 
Syntactic sugar
Primitives

Zoem primitives may expand (which is the same as evaluate) one, several, or all of their arguments before using them. Such arguments are enclosed by double angle brackets in the listing below. The inside-out type evaluation is done recursively and works for arbitrary levels of nesting. An argument which is first expanded and is then interpreted as a label is thus written <label> in the primary entry. In the definition text accompanying the entry, the expanded argument is simply refered to as <label>, so the extra pair of brackets is dropped.

Each primitive below has a little paragraph with the caption Result text. It gives a summary of 'what comes out'. Note that the result of macro expansion is always passed to the parser again, so the result text is again subject to expansion.

These are special. Refer to section SGML/HTML/XML syntactic sugar cubes. The angle brackets are part of the syntax, do not confuse them with the angle brackets used below to enclose arguments. These primitives are respectively used as \<*any*> and \<*any*>{*any*}, so the positioning of arguments is different from all other zoem primitives.
 
\!
This primitive is triggered by an active backslash followed by a consecutive run of exclamation marks, which is not followed by an opening curly. The sequence is called a delay sequence, and its arity is the count of backslashes. A single exclamation mark is stripped (i.e. the arity is decremented) and the sequence is no longer subject to the current expansion stage. It is used to construct valid zoem input, which is usually redirected to file with the copy filter, stored using \setx#2, or used in nested occurrences of \apply#2, \inspect#4, and other primitives. Other uses are possible, the main thing is that one should keep a clear view of the meta-programming implied by \!. Refer also to the \eval#1 primitive.

Example
The primitive \eval#1 evaluates its argument a single time, and passes it on for further evaluation. The following are fully equivalent:

\set{foo}{zut} \eval{\!foo} \foo

whereas \!foo would pass the sequence \foo to the filtering stage, where it will yield a (non-fatal) error message. Similarly, \eval{\eval{\!!foo}} is equivalent to the above.

Result text
A delay sequence of decremented arity.

 
\!#1:  \!{<any>}

This primitive is triggered by an active backslash followed by a consecutive run of exclamation marks, which is in turn followed by a block. The block is called a delay scope. The arity of the delay scope is the count of backslashes found in the run. A single exclamation mark is stripped (i.e. the arity is decremented); if no further exclamation marks remain (i.e. the arity becomes zero) then the introducing backslash and the delimiting curlies are stripped as well. The result (including the contents of the block) is passed on and is no longer subject to the current expansion stage. The same observations hold as those made for the previous entry. Refer also to the \eval#1 primitive.

Additionally, blocks that are protected by the delay primitive will be skipped during parameter interpolation.

Result text
<any>, if the arity of the delay scope just found was equal to one, otherwise, <any> put in a decremented delay scope. <any> will in both case no longer be subject to the current expansion stage.

 
\$#2:  \${<str>}{<any>}
This is a shortcut for activating output for a particular device. If \__device__ expands to <str>, <any> is passed on for expansion, otherwise it is ignored. The following two are equivalent:
\${html}{Seen only in the html device} \if{\cmp{eq}{\__device__}{html}}{Seen only in the html device}{}

Result text
Either none or <any>.

 
\apply#2:  \apply{<<key-sig|anon-key>>}{<<vararg>>}

The first argument is expanded before use. It should expand either to the signature of a user key, primitive or builtin taking arguments, or to a tagged anonymous key. Examples of the first are foo#k and "bar::baz"#k, the latter takes the form _#k{..}. If you use an anonymous key containing macro sequences, be sure to escape whole or part of the anonymous key, depending on your needs. The expansion of _#2\!{{<any>}} for example, will result in _#2{<any>}. Primitives can used in both quoted and regular syntax.

The second argument should result in a vararg. \apply#2 extracts k elements at a time from <vararg>, and applies the key resulting from the first argument to each vector of k elements successively. Any elements remaining in <vararg> are ignored.

Result text
Entirely depending on the key specified in the first argument.

 
\begin#2:  \begin{<label>}{<<vararg>>}

\begin#2 pushes a new dictionary onto the dollar dictionary stack which is popped by the matching \end#1.

\begin#1 is an alias which invokes \begin#2 with an empty <vararg> argument.

\begin#2 pushes the begin expression associated with <label> via \env#4. The <label> part is not expanded. The second argument <vararg> consists of consecutive scopes denoting key-value pairs. It is expanded before use and is allowed to be empty. The keys (which are the odd-numbered scopes, starting with one) in <vararg> must be such that prepending a dollar sign ($) to them yields a valid key signature. That signature will be used to set a dollar key in the newly pushed dollar dictionary that expands to the value part associated with the key (specified as the consecutive even-numbered scope in <vararg>). Alternatively, since the 07-333 release, it is also possible to explicitly include the dollar sign in the keys rather than having them prepended.

The \env#4 invocation that defines the environment likely sets defaults for the dollar keys (via the second argument of \env#4) that can be set as described above.

The pushing of a dictionary provides a means for shadowing and localization with nested \begin#2 statements. By associating dollar keys with an environment, these keys can be given different meanings in nested environments - the previous meaning will be restored once an environment is closed. The advantages are that the environment does not have to exercise \push#1 and \pop#1 itself, that the user dictionary stack is not unnecessarily extended (saving look-up time), and that the 'dollar' look of a key such as \$align signals that it will automagically work in nested enviroments. Of course, the latter is still the responsibility of the author of the environment.

Result text
The string associated with <label> via \env#4.

Example I
The zoem faq macros define a faqsec environment, for which two additional arguments are required. It is used for example as

\begin{faqsec}{{ref}{misc}{cap}{Miscellaneous questions}} ... \end{faqsec}

The ref key introduces the label, the cap key introduces the caption.

Example II
The itemize environment in the zoem generic package allows one additional and optional argument. This argument, if present, must contain a vararg, and is used to set options related to the itemize environment. It is used for example as

\begin{itemize}{ {interitem}{0} {flow}{compact} {mark}{\*{itembullet}} {align}{right} } ... \end{itemize}

Internally, the itemize environment maps these options to dollar keys. Because a unique dollar dictionary is associated with each environment, this makes it possible for nested itemize instances to have separate namespaces.

Result text
The (unexpanded) string stored in the third argument of the corresponding \env#4 invocation.

 
\catch#2:  \catch{<type>}{<any>}

This will process <any>. Depending on <type> the result is accepted as succesful. If <type> is towel, any occurrence of \throw{towel} in <any> is caught, and the truncated result is further processed. For towel, zoem errors are not caught but cascade/escalate further down/up. If <type> is error, any error in <any> is caught, and the truncated result is further processed. If <type> is done, no exception is accepted. It is possible though to use throw{done{..}} which will stop processing without generating an exception. See also \throw#2.

Output will be truncated in case an error or exception was caught. The status, currently one of done, towel, or error, is written in the session macro \__zoemstat__.

Result text
The possibly truncated result of expanding <any> in case of a caught exception or error, else the full result.

 
\cmp#3:  \cmp{<str>}{<<any>>}{<<any>>}

The last two arguments are expanded. Their results are compared as strings. The first argument must be one of the labels lt|lq|eq|gq|gt|ne|cp. In case it equals one of the six labels lt|lq|eq|gq|gt|ne, this primitive puts in place the associated boolean as a string (i.e. either 0 or 1). In case the label equals cp, it puts in place the result of the string compare (as a string), namely one of -1, 0, or 1.

Result text
Either the string enconding of a boolean (0 or 1) or the string encoding of the ternary value resulting from a string compare (-1 or 0 or 1).

 
\constant#1:  \constant{<vararg>}

<vararg> must have an even number of arguments. These are interpreted as pairs. The first of each pair must enclose a string that does not contain any of the characters *, \, {, or }, say string <keystr>. The second encloses a string that will be interpreted in device space, say string <valstr>. When a sequence \*{<keystr>} is encountered, it is interpreted as \@{<valstr>}. This is done at filter time only, the sequence is skipped during macro expansion. It is not allowed to use a sequence \*{<keystr>} in device scope, e.g. \@{\*{<keystr>} is illegal. For further information see section Device scope.

Result text
None.

 
\def#2:  \def{<key-sig|data-seq>}{<any>}

Bind second argument to the key or access sequence in the first argument. This primitive will complain if a binding exists already, but it will overwrite the previous binding and continue anyway. Use \set#2 if you do no want to be warned for overwriting. Examples of usage:

\def{foo}{FOO} \def{foo#1}{The FOO of \1} \def{foo#2}{The FOO of \1 and \2} \def{$foo#2}{The $FOO of \1 and \2} \def{"foo::oof"#3}{\foo{\1}{\2}\foo{\2}{\3}}

These examples are all of type key-sig. See the Tree data section for examples of type data-seq (this pertains to multi-dimensional data storage). See the Macro expansion section for the forms that keys may take. A key signature is the name of a key with appended to it the number of argument that the key takes, if any. If the key takes no arguments, than the key signature is identical to the key name.

If you want the value to be bound to be expanded before binding it, use either \defx#2 or \setx#2. This works the same for data keys.

Result text
None.

See also
\set#3.

 
\defx#2:  \defx{<key-sig>}{<<any>>}

The second argument is expanded and stored in the key <key-name>. This primitive will complain if a binding for that key exists already, but it will overwrite the previous value anyway.

Result text
None.

See also
\set#3.

 
\defined#2:  \defined{<type>}{<<access>>}

<type> is one string of key, lkey, data, primitive, builtin, zoem or ENV. The second argument is expanded before use. For the type key, the <access> argument is looked up as a key signature in either the user dictionary stack or the dollar dictionary stack. For the type lkey, it is looked up only in the top level dictionary. For the type data, the <access> argument is interpreted as a data access sequence. For the type primitive, the <access> argument is looked up in the zoem primitive table. For the type builtin, the <access> argument is looked up in the zoem builtin macro table. The type zoem corresponds with the union of the types primitive and alias. For the type ENV, it is checked whether it exists as an environment variable (which can be retrieved using the \__env__#1 primitive). This primitive pushes the string 1 if the result is indeed a valid reference, it pushes the string 0 otherwise.

Result text
The string encoding of a boolean (0 or 1).

 
\dofile#2:  \dofile{<<file name>>}{<char[!?]><char[+-]>}

Open a file and process its contents while keeping track of line numbers. Depending on the second argument, absence of the file is either allowed or not, and its interpreted contents are output or not. The fact that <file name> is first expanded allows you to specify file names such as \__fnbase__.zyx.

Zoem may search for a file in several locations until it is found. The process of locating a file is described in section File search path .

When found, the file is opened according to the specification in the second argument. This argument must contain exactly two characters, the first one of [!?], the second one of [+-]. The first character indicates whether the file is allowed to be absent. A '!' implies that absence is fatal, a '?' permits absence. The latter is useful e.g. when creating a Table Of Contents file. The second character indicates whether the interpreted file should be filtered and output or not ('+' for yes and '-' for no). Macro packages typically need interpretation only, whereas concatenation of document parts (c.q. chapters) stored in different files requires that the interpreted content is also filtered and output. The following aliases are available:

\input{fname} \dofile{fname}{!+} \import{fname} \dofile{fname}{!-} \read{fname} \dofile{fname}{?+} \load{fname} \dofile{fname}{?-}

The contents of <file name> cannot be captured. If you need to capture the contents of a file, use \finsert#1 or \zinsert#1.

Result text
Technically none. Of course the processing of <file name> may result in output, depending on the mode of opening. However, this result text cannot be captured. For example,

\setx{foo}{\dofile{bar}{!+}}

will result in the file <bar> being processed and output via the standard output mechanisms, while the key \foo will have the empty string as value.

 
\dowhile#2:  \dowhile{<any>}{<condition>}

<any> is expanded and concatenated to the result text until <condition> exands to something that is nonzero when interpreted as an integer. <any> is expanded at least one time.

 
\__env__#1:  \__env__{<name>}

Looks up <name> in the environment.

Result text
The corresponding value if <name> exists in the environment, the empty string otherwise.

Note
This primitive yields identical results for names not in the environment and names in the environment for which the value is empty. Use \defined#2 to check whether <name> exist.

 
\end#1:  \end{<label>}

Expands the end definition associated with <label> via \env#4.

Result text
The string associated with <label> via \env#4.

 
\env#4:  \env{<label>}{<<any1>>}{<any2>}{<any3>}

Stores expanded <any1> and unexpanded <any2> for later use with \begin#2 (when given argument <label>) and unexpanded <any3> for later use with \end#1 (when given argument <label>).

<any1> may contain a vararg denoting key-value pairs. These will be set for each \begin#2 invocation in the corresponding dollar dictionary. It provides a convenient mechanism to set default values for keys that can be passed in the second argument of \begin#2. Note that keys are passed as regular macro signatures, but they are then transformed to dollar keys by prepending a dollar sign. Environments are tighly linked to the dollar dictionary stack. Read more about this in the description of \begin#2.

With each \begin#2 invocation, after <any1> is processed as indicated above, <any2> will be pushed onto the input stream. Before this, \begin#2 defines the keys \$__args__ and \$__xargs__. These contain respectively the vararg that was passed as the second argument of \begin#2 and the same vararg after it was expanded. These keys can be used in <any2>. One possible usage is to pass the key-values on to other environment invocations. This is a likely scenario in case one environment is a thin customization wrapper around a full-fledged base environment.

Result text
None.

 
\eqt#3:  \eqt{<str>}{<<num1>>}{<<num2>>}

The last two arguments are expanded. Their results are compared as numbers. The first argument must be one of the labels lt|lq|eq|gq|gt|ne|cp. In case it equals one of the six labels lt|lq|eq|gq|gt|ne, this primitive pushes the associated boolean as a string (i.e. either 0 or 1). In case the label equals cp, this primitive pushes the result of the integer compare, namely one of -1 (if the result of <any1> is smaller than the result of <any2>), 0 (equal to), or 1 (greater than).

Result text
Either the string enconding of a boolean (0 or 1) or the string encoding of the ternary value resulting from a numeric compare, (-1 or 0 or 1).

 
\branch#1:  \branch{<<vararg>>}

Two arguments are successively taken from <vararg>. The first is expanded and then evaluated as an integer. If the integer is nonzero, the second argument is expanded and everything else is ignored. Otherwise the procedure is repeated. If no (odd) argument matches, and the <vararg> has an odd number of arguments, the last argument is put in place. It can be considered a default, else, or failure clause.

 
\eval#1:  \eval{<<any>>}

Expands <any> and passes it on for further evaluation. This can come in handy when complicated requirements demand zoem acrobatics. This primitive used to be implemented as a macro; it is fully equivalent to

\set{eval#1}{\apply{_#1{\!1}}{\1}}

The above macro works as follows. First, \apply#2 expands both of its arguments. The second argument is the data it received from \eval, i.e. the latter's single argument. At this stage, the data is thus expanded for the first time. \apply#2 also expands its first argument. The sequence \!1 is contracted to the sequence \1. The \1 needed by \apply#2 needs to be protected by the interpolation that occurs when eval#1's argument is interpolated. Expansion of \apply#2's first argument thus yields the anonymous key _#1{\1} — a key that simply copies it argument and passes it on for further expansion.

Example
\foo and \eval{\!foo} are fully equivalent. \!foo on the other hand, expands to \foo and is then passed to the filter stage.

See also
\!, \!#1.

Result text
<any> gone through two stages of interpretation.

 
\exit

goodbye world. This is a disgraceful exit for use when some error test presumably yields true. See also \throw#2.

Result text
None.

 
\f#2:  \f{<fun>}{<<num1>>}

Expand the last argument, interprets the result as a number, applies the operand specified by <fun>, and puts the result in place. <fun> can be one of

floor, ceil, round, abs, sign, inc, dec, not, drand, irand, and that's about it. Mode \f{drand}{<num>} yields a floating point number in the range [0-<num>], and mode \f{irand}{<int>} yields an integer in the range [0-<int>), that is, the argument <int> itself is excluded from the range.

For a wider range of mathematical functions, refer to the \let#1 primitive.

Result text
The string encoding of a number.

 
\f#3:  \f{<fun>}{<<num1>>}{<<num2>>}

Expands the last two arguments, interprets the results as numbers, applies the operand specified by <fun>, and puts the result in place.

Most arithmetic is done using floating point arithmetic (with the C double type). Integers are preserved if possible. Since nearly everything is treated as a string in zoem, this simply means that no decimal fraction is printed when the number is output. A number is considered integer if the difference with the integer nearest by is less than the precision (1e-8) and if it can be represented as an integer using the C long type. Otherwise it is output in decimal representation of the underlying floating point representation.

<fun> can be one of

*
Multiplication.
+
Addition.
-
Subtraction.
/
Does true division, returns real.
%
Modulus.
and
Boolean and, results in 0 or 1.
or
Boolean or, results in 0 or 1.
div
Does integer division.
mod
Same as %.
pow
Power.
max
Maximum.
min
Minimum.
ceil
Nearest by higher multiple, e.g. \f{ceil}{12}{5}=15.
floor
Nearest by lower multiple, e.g. \f{floor}{12}{5}=10.

For a wider range of mathematical functions, refer to the \let#1 primitive.

Note
and and or short-circuit.

Result text
The string encoding of a number.

 
\fv#2:  \fv{<fun>}{<<vararg>>}

Expands the second argument and interprets it as vararg, and applies the operator specified by <fun> to the elements of vararg.

<fun> can be one of

*
Multiplication.
+
Addition.
and
Boolean and.
or
Boolean or.
max
Maximum.
min
Minimum.

Note
and and or short-circuit.

Result text
The string encoding of a number.

 
\finsert#1:  \finsert{<file name>}

The argument is expanded and interpreted as file name. The file is read, and every \, {, and } is escaped (resulting in one of \\, \{, and \}) The altered contents are then put in place. See also \zinsert#1. If file can not be opened, the empty string results.

Note
This primitive cannot be used to read inline files whereas \zinsert#1 can. The reason is that inline files have to satisfy zoem syntax. \finsert#1 can be used to read arbitrary data.

Result text
The escaped contents of <file name> or the empty string if file can not be opened.

 
\format#2:  \format{<<fmt>>}{<<vararg>>}

NOTE
This primitive was changed in an incompatible way in the 07-333 release. The special case specification syntax was discarded and replaced by the more robust and extensible key-value based syntax described below.

The primitive formats elements from <vararg> according to the format specification in <fmt>. A format string may contain normal characters that will be output, and meta sequences. A meta sequence is started with the percent character % and either followed by a block or by another percent sign. A meta sequence consisting of two consecutive percent signs (%%) will be skipped and result in the output of a single percent sign. Otherwise, the meta sequence will format the next argument from <arg> according to the specification in the block. A specification consists of a series of key-value pairs that may occur in any order. The key is called the directive and the supported directives are:

{padding}{<any>}

The literal string padding is the directive and indicates that the value specifies the padding. The <any> content of the value block is used as the padding string. By default spaces are used for padding (and incidentally runs of spaces will be squashed unless \@{\w} is issued). Padding is applied if the width of the field exceeds the width of <arg> plus the width of the optional delimiter(s) described below.

 
{delimit}{<delimiter>}[{<delimiter>}]

The content of the first block is inserted inbetween the padding and <arg>. If centered alignment is used, this will be done on both sides. By default no such delimiter is used. It is possible to specify two <delimiter> arguments. In that case the first specifies the left delimiter and the second specifies the right delimiter.

 
{align}{left|center|right}

The directive is align, the value is one of left, center, or right and specifies how the argument taken from <vararg> is to be aligned.

 
{width}{<num>}

The directive is width, the value should be a positive integer number denoting the desired width of the field on which <arg> is to be printed.

 
{length}{{key}[{args}*]}

The directive is length, the value consists of one or more blocks. The first value block should contain the name of a macro. This is for when you want to customize the way in which the length of strings is computed. The macro will be used to compute the lenght of strings under consideration, using entries in the double directive as appropriate (see below). This allows you for example to do alignment in <pre> formatted blocks in html, while keeping the possibility to insert elements that do not take up any width (e.g. links). The first value block should contain the name of a macro. A likely candidate is \length#1, which should be specified simply as length. The first argument that is given to this macro will be the string under consideration. The rest of the value blocks, if any, will be given as additional arguments.

Currently, this custom length computation is only applied to the argument that is being formatted and the two delimiters if present. All three of these can be replaced, for the purpose of length computation, by placeholders using the double directive.

 
{double}{{[{key}{value}]*}}

The directive is double, the value consists of a single block containing a vararg. This is used to specify placeholders when computing the length of elements. The vararg contains placeholder types as keys and the corresponding placeholder values. It is currently possible to specify three different types of placeholders. These are the argument to be typeset, specified with the placeholder key arg, the left delimiter, specified with delimit-left, and the right delimiter, specified with delimit-right.

NOTE
The value is enclosed in a block, as part of the key-value specification employed by the double specification. The value itself is a block containing key-value pairs (again specified as curly-delimited blocks). So be sure to supply the correct number and nesting of blocks.

 
{alignat}{{<pivot>}{<width>}}

The directive is alignat, the value consists of two blocks. This is used to specify alignment. The content of the first value block is used as the string on which to align. The content of the second block is used as the width on which the first part of <arg> (up to and including the alignment substring) will be right-aligned. If the length specification is used as well, the length macro specified therein will be used to compute the width of the string specified in the first block.

 
{reuse}{<num>}

This instructs zoem to reuse the current specification for another <num> arguments taken from <vararg>. Instead of <num> it is possible to specify {reuse}{*}. This will reuse the current specification until all arguments have been exhausted.

 
{border}{{<left>}{<right>}}

This borders the result of the current specification with <left> and <right>. This is useful in conjunction with the reuse specifier, for example for adding device line-breaks to each formatted item.

Example

\format{%{{align}{right}{width}{10}{reuse}{*}{padding}{{'}{}}}}{ {beauty}{lies}{in}{the}{eye}{of}{the}{beholder} }

results in

''''beauty''''''lies''''''''in'''''''the'''''''eye''''''''of'''''''the''beholder

Result text
The formatted string.

 
\formatted#1:  \formatted{<any>}

This removes and adds white space from its arguments via the following rules:

It skips any \@{..} enclosed sequence.

It skips any \<..> enclosed sequence - note that the contents eventually will end up in \@{..} (at) scope.

It removes all spaces, tabs, and newlines it encounters otherwise.

It inspects and (after inspection) removes all \`{..} enclosed sequences it encounters. During inspection, \formatted#1 maps 's' to a space, 't' to a tab, and 'n' to a newline.

If the sequence \`{<} is encountered (not in at scope), \formatted#1 starts copying literally without munging whitespace; it resumes its normal mode of operation after encountering the sequence \`{>}.

This is useful for writing legible macro files while exercising full control over whitespace (modulo Zoem's white space munging rules).

Result text
The argument in its unformatted form.

 
\get#2:  \get{<dict-label>}{<key-sig>}

The user stack is searched from top to bottom for dictionaries with label <dict-label>, and those dictionaries are searched in order for a key with signature <key-sig>. The first succesful match is retrieved and its definition is pushed onto the interpretation stack. It is an error if no such definition is found.

Note
The label of the default user dictionary is ''. This ties in with the syntax \''keysig, used to specify the user dictionary stack. So the following:

\set{user}{Jill} \push{foo} \set{user}{Phil} \push{bar} \set{user}{Bill} \get{''}{user} \get{foo}{user} \get{bar}{user}

yields output Jill Phill Bill.

Note
It is currently not possible to access keys that take arguments.

Result text
The result of processing the retrieved definition.

 
\if#3:  \if{<<int-expr>>}{<any1>}{<any2>}

The first argument is expanded and interpreted as an integer. If it is nonzero, <any1> is pushed on the interpretation stack and <any2> is ignored, vice versa if it is zero.

Result text
Either <any1> or <any2>.

 
\inspect#4:  \inspect{<<vararg>>}{<<reg>>}{<<any|anon key>>}{<<any>>}

status
Experimental

All arguments are expanded before use. <vararg> currently recognizes a single key mods. The value of mods may contain a comma-separated list of the following directives. Repeated use of mods is allowed.

posix icase dotall iter-lines iter-args match-once discard-nmp discard-nil-out discard-miss count-matches

The posix directive is currently required, specifying that POSIX regular expressions are used. The future might bring other regex syntaxes.

Argument <reg> specifies a (POSIX) regular expression. Before being passed to the match engine, it undergoes UNIX and TILDE tilde replacement as described in the zoem manual.

Consult the POSIX documentation or the regex(7) manual page for a description of posix regexp syntax.

The expansion of <any|anon key> can either result in plain data or in an anonymous key. The expansion of the last argument results in data to which the regex <reg> is successively applied.

Interpolation
If the second expansion starts with the pattern _#k{ it is assumed to be an anonymous key. The subpatterns from the matched pattern are interpolated by the key, and the entire matched pattern is substituted by the interpolation. Else, the matched pattern is simply replaced by the expansion.

icase induces case insensitive matching. dotall makes the dot . match any character, including the newline. iter-lines causes matching to be applied to lines shifted from the data (i.e. data is split on newlines). iter-args causes matching to be applied to blocks shifted from the data (which should obviously be a vararg). match-once inspects each element under consideration only once. count-matches replaces the data by the count of matches. In conjunction with iter-lines or iter-args it yields the counts on separate lines and in separate blocks, respectively. discard-nmp discards non-matching parts. discard-miss removes any lines or blocks which are empty after inspect is done with it. discard-nil-out discards any strings or lines or blocks that are empty after matching and optionally interpolation has been applied.

Bugs
The GNU implementation of POSIX regexes was at some point known to be buggy for long strings and/or long matches.

A search pattern consisting of a single word boundary or the start-of-string token (^) will match at each position, because after a succesful match \inspect#4 simply resumes searching for a new match by skipping to the end of the previous match (and adding a single position if the match had width zero and offset zero). Similar but not yet noticed bugs may exist.

Nevertheless, this can be a very useful primitive for the occasional odd job, and it should always work except for the cases just mentioned. If you have a complicated instance of \inspect#4, test it first in isolation. Consider sending a bug report in case you find one (a bug, or a bug report).

Result text
Depending on the presence of a match and the modifiers given.

 
\length#1:  \length{<<any>>}

Computes the length of <any> and puts this in place. It takes into account the zoem escape sequences \\, \{, and \}. The future may bring a generalized \length#2 primitive that provides different ways of measuring string length.

Result text
The length of any <any>.

 
\let#1:  \let{<<let expression>>}

The \let#1 primitive puts zoem in arithmetic mode and the contents are parsed accordingly. All of C's operators are supported including the logical, bitwise, and comparison operators as well as the ternary operator. The operators ** and // are added, which respectively denote exponentiation and integer division. Operations or functions resulting in integers are tracked, and the result will be stored in the integer type used (typically long) if possible. Thus one may find that

\let{2**42} \let{2**22}

respectively result in 4398046511104.0 and 2097152.

The precedence rules used by Zoem are simpler than C's. The respective groups of logical, bitwise, and comparison operators all have identical precedence internally, and associate from left to right.

Most of the ANSI C math functions are supported, with in addition max and min. The functions round, sign, and abs behave slightly different from their C counterparts, as they result in integer results if no overflow occurs.

At any place where an atomic type is expected one is allowed to insert a zoem macro invocation. It will be evaluated and the result will be interpreted as a number. Evaluation will take place in the order as dictated by the precedence rules governing the expression.

The logical operators shortcircuit and the ternary operator evaluates only one of its branches. This can be used to create side effects, such as in

\let{\bar && \group{\set{foo}{zut}1}}

This sets foo only if bar evaluates to a non-zero number. The trailing 1 in the group macro is good practice because \let#1 expects a number to be the result of any macro it encounters. It could have been any other number, or a macro or sequence of macros evaluating to a number. The group macro is a predefined macro that does nothing except passing its arguments. It is necessary in this concocted example because any occurrence of a macro within \let#1 is interpreted as a number by itself. The sequence \bar \bar would for example be syntactically identical to 1 1, which is incorrect.

Result text
A number.

 
\nargs#1:  \nargs{<any>}

The argument is not expanded. It puts in place a number that indicates whether this argument could be parsed as a number of scopes or whether it is a regular argument. The following list of examples illustrates the rules according to which the number is created.

\nargs{{abc}def} : -2 \: neither fish nor fowl \nargs{abc} : -1 \: regular argument \nargs{abc{def}} : -1 \: regular argument too \nargs{} : 0 \: empty vararg (not empty regular arg) \nargs{ } : 0 \: empty vararg again \nargs{{abc}} : 1 \: vararg with 1 argument \nargs{{abc}{def}} : 2 \: vararg with 2 arguments \nargs{ {abc} {def} } : 2 \: vararg with 2 arguments \: etc.

From this it is seen that if the first non-whitespace character is an opening curly the primitive expects to find a number of scopes with nothing inbetween or trailing. If it does not succeed the result text is set to the special value -2.

Result text
integer

 
\pop#1:  \pop{<label>}

Pops a dictionary from the user dictionary stack pushed earlier by \push#1. The tag <label> must be same as the one supplied by that specific \push#1 invocation.

Result text
None.

 
\protect#1:  \protect{<<any>>}

The argument is expanded. Subsequently, all backslashes and curlies are escaped. The resulting text is put in place.

Result text
<any> with backslashes and curlies escaped.

 
\push#1:  \push{<label>}

Pushes a new dictionary onto the user dictionary stack with tag <label>. The corresponding \pop#1 should use the same tag. Note that \defined#2 with the lkey directive checks only the top-level dictionary, whereas \defined#2 with the key directive checks the whole stack of dictionaries. Also, \undef#1 only removes a key from the top-level dictionary. There is currently not a way to access keys based on dictionary label.

Result text
None.

Example of usage:

\def{num}{1} \push{foo} \def{num}{2} \push{bar} \def{num}{3} \push{tim} \def{num}{4} \pop{tim} num is \num \pop{bar} num is \num \pop{foo} num is \num

results in

num is 3 num is 2 num is 1
 
\register#2:  \register{<tag>}{<any>}

Register <any> to be processed at the occassion specified by <tag>. The only <tag> currently supported is END. END registrees are processed only after all regular input has been processed. Multiple \register#2 invocations are allowed. Registrees are processed in the order of registration.

Result text
None at time of registering, the result of <any> at time of processing.

 
\set#2:  \set{<key-sig>}{<any>}

As \def#2 above, except that \set#2 will not complain if the key labeled by <key-sig> already exists.

Result text
None.

See also
\set#3.

 
\setx#2:  \setx{<key-sig>}{<<any>>}

The second argument is expanded and stored in the key <key-name>. Besides simply storing the expansion of an expression, it can also be used to do trickier things as

\def{bar}{klaas} \setx{foo#2}{\bar says \1 and \2} \foo{x}{y} klaas says x and y

If you need lambda-like capabilities, take note that you can use \!k or \!{\k} to construct a positional parameter \k, if you want to interpolate arguments into a key that will later take other arguments. Like this:

\: is there any use for this wacky stuff? \def{lambda#2}{\setx{\1#1}{\2 says \!1}} \lambda{foo}{bar} \foo{moo} bar says moo

Take care: the \dofile#2 key outputs to the default output file. If you need to include the contents of a file within a \setx#2 call, you need to use \finsert#1 or \zinsert#1 in conjunction with \setx#2.

Result text
None.

See also
\set#3.

 
\set#3:  \set{<{modes}{..}{if}{..}{unless}{..}{dict}{..}{start}{..}{width}{..}>}{<key-sig>}{<any>}

This primitive encompasses all of the previous four as well as providing additional modes of operation. The first argument is a vararg storing key-value pairs. The possible keys are modes, if, unless, dict, start and width. All of these are optional.

The <modes> value, if present must be a string over the following characters.

a

append to the key, do not overwrite, create if not existing.

c

conditionally; only set if not already defined.

e

existing; update existing key, possibly in lower dictionary.

g

global; set in the global (bottom) user dictionary.

u

unary; do not interpret vararg in <any> as key-value list (data keys only)

v

vararg; interpret vararg in <any> as key-value list (regular keys only).

w

warn if key exists (like \def#2 and \defx#2).

x

expand argument (like \setx#2 and \defx#2).

The u directive applies when setting data. The v directive applies when setting regular keys. In this case, <key-sig> must be empty, and <any> is treated as a vararg of repeated key-value pairs. Directives can be combined as needed.

Note that keys in the global user dictionary can be accessed even if other dictionaries are pushed using the syntax \''foo.

The if and unless directives can be used to trigger action (i.e. definition of keys) only if the corresponding clause evaluates to non-zero or zero, respectively.

The dict directive must be followed by a dictionary name in the subsequent block. The dictionary stack will be searched for a dictionary with this name. The type of dictionary is derived from the key signature. This is either the dollar dictonary used for the dictionary stack associated with \begin#2 (if the key starts with a dollar sign $), or the default user dictionary.

The start and width directives only work if a single key is set. Their values should evaluate to integers <start> and <width>. The key will be set to its old value with a segment of length <width> starting at offest <start> replaced by <any>. Offsets are zero-based and units are in bytes.

Result text
None.

See also
\def#2, \defx#2, \set#2, \setx#2.

 
\special#1:  \special{<<vararg>>}

<vararg> is expanded before use. It must have an even number of arguments. These are interpreted as pairs. The first of each pair must enclose an integer in the range 0-255 or one of the special token identifiers -1, -2 or -3. The integers in the range 0-255 are interpreted as character indices The characters indexed -1, -2 and -3 correspond with the zoem glyphs \~, \|, and \- respectively. The second element in each pair defines the string to which the character specified by the first element must be mapped. This string is interpreted in device scope. See the Device scope section for simple uses.

A key may occur multiple times. The corresponding definitions are stacked away and will be accessed according to the current special level (cf. the section on mapped characters in device scope).

Repeated use of \special#1 does not cause the removal of previous definitions, with one exception: If \special#1 is invoked with no arguments at all then all definitions are removed.

Note
Be sure to use delay sequences as appropriate, noting that vararg is expanded. Below is how Portable Unix Documentation encodes a line break in troff:

{-2} {\!N.br\!N}

Zoem interprets the value and accordingly associates the device scope sequence \N.br\N with the token \|. The escape sequence \N will thus be processed during the filter stage as is appropriate. Without the delay sequence zoem would try to expand \N during processing of the \special#1 primitive.

Result text
None.

 
\switch#2:  \switch{<<pivot>>}{<vararg>}

The first argument is expanded. Subsequently, two arguments are successively taken from <vararg>. The first is expanded and string compared with <pivot>. If they match, the second argument is expanded and everything else is ignored. If they do not match, the procedure is repeated. If no (odd) argument matches, and the <vararg> has an odd number of arguments, the last argument is put in place. It can be considered a failure clause. This primitive does not have fall-through behaviour; at most one branch will be handed to the parser.

Different cases can be grouped in a vararg. If \switch#2 recognizes that the test argument can be parsed as a vararg it will exctract all the corresponding sub-arguments. If the pivot matches any of these the branch corresponding to the test argument will be taken.

Result text
Either the first block associated with a matching case of <pivot>, the failure clause, or nothing at all.

 
\system#3:  \system{<cmd>}{<<args>>}{<<data>>}

By default this primitive is disallowed. The first argument is the name of a system command. The environment variable PATH is used in tracing the location of the command. If <data> is non-empty, it is first unprotected, that is, escaped backslashes and curlies are unescaped. The resulting text is then fed to command <cmd> with arguments <args>. The latter, if non-empty, must be specified as a vararg, even if only a single argument is present. Should execution of the command (be it with or without data) result in output on STDOUT then the latter is captured, backslashes and curlies are escaped (i.e. the output is protected), and the result is put in place. STDERR is the same as it is for the parent (zoem).

Note
The security implications of this feature. By default zoem will ignore \system. The command line option --unsafe will cause zoem to prompt for user confirmation (if prompting is not possible it will ignore again) for each encountered \system invocation. The option --unsafe-silent will silently allow all \system invocations. The option --allow=cmd[:cmd]* explicitly specifies which commands to allow silently. It is also possible to use this option repeatedly rather than separate different commands by colons.

If the zoem command line option --system-honor is used, zoem will exit if a system command fails or is ignored.

A simple exit status is written in the variable \__sysval__: it is zero (0) on success, and one (1) on failure.

Refer to the manual page of the zoem interpreter for more information on --unsafe, --unsafe-silent, --allow=, and --system-honor.

Built-in macros \system#2 and system#1 exist. The former drops the <data> argument, the latter also drops the <args> argument.

Example

\system{sort}{{-n}}{\finsert{foo}} \system{ls}{{-l}{-a}} \system{date}

Result text
The output captured (and then protected) from <cmd>'s STDOUT, if any.

 
\table#5:  \table{<<row length>>}{<any1>}{<any2>}{<any3>}{<<vararg>>}

The first argument is expanded and interpreted as an integer, say k. Successively, vectors of k elements are shifted from <vararg>. Each vector is bordered on the left with <any1>, bordered on the right with <any3>, and all elements in the vector are separated with <any2>.

This primitive is perhaps not really needed as its functionality is largely covered by \apply#2.

Result text
The blocks from <vararg> interspersed in a table-like manner with <any1>, <any2>, and <any3>.

 
\textmap#2:  \textmap{<vararg>}{<<any>>}

Apply one or more transformations to <any> and put the result in place. <vararg> takes a succession of key-value pairs. The associated transformation are applied in order. The supported transformations are:

{word}{ucase}
Uppercase <any>
{word}{lcase}
Lowercase <any>
{number}{roman}
Convert number to Roman
{number}{alpha}
Convert number to letters
{repeat}{<num>}
Concatenate <num> copies of <any>
{caesar}{<num>}
Apply caesar encryption
{vigenere}{<key>}
Apply vigenere encryption
{vigenerex}{<key>}
Apply vigenere encryption and include space

The roman transformation is e.g. used to equip the itemize environment (defined in the generic package) with fancy roman numbering. To get uppercase roman, do this:

\textmap{{number}{roman}{word}{ucase}}{\your_nice_counter}

The alpha transformation maps its argument to a string over the alphabet _a-z, i.e. all the set of all lowercase letters with the underscore added. This set is simply used for counting in base 27, with the underscore playing the role of zero.

Result text
The transformed text.

 
\throw#2:  \throw{<towel|error|done>}{<<any>>}

Quit parsing, unwind stack until some occurrence of \catch#2, \try#1 captures this throw.

The throw \throw{done} is also unconditionally caught by \while#2 and \eval#1. If \throw{done} is encapsulated by neither of these four primitives it means that processing of the current file is stopped, and processing at the including file, if applicable, is resumed.

<any> is digested; if it has positive length the result is issued as a diagnostic.

Note
Many primitives evaluate one or more of their arguments before use, as indicated in this manual. An occurrence of \throw{done} in such an argument, if not caught, will be treated like an error. It is possible to use \throw{done} in such an instance by encapsulating the argument in \eval#1.

Result text
None, affects the result text of the embedding scopes.

 
\tr#2:  \tr{<vararg>}{<<any>>}

<vararg> contains key-value pairs. The accepted keys are from and to which must always occur together, and delete and squash. The values of these keys must be valid translation specifications. This primitive transforms <any> by successively applying translation, deletion and squashing in that order. Only the transformations that are needed need be specified.

The syntax accepted as translation specification is almost fully compliant with the syntax accepted by tr(1), with three exceptions. First, repeats are introduced as [*a*20] rather than [a*20]. Second, ranges can (for now) only be entered as X-Y, not as [X-Y]. X and Y can be entered in either octal or hexadecimal notation (see further below). As an additional feature, the magic repeat operator [*a#] stops on both class and range boundaries. Finally, character specifications can be complemented by preceding them with the caret ^. See further below for examples where these features are used.

Preprocessing
The values (not the data <any>) are subjected to UNIX tilde expansion as described in the the zoem manual.

Syntax
Specifications may contain ranges of characters such as a-z and 0-9. Posix character classes are allowed. The available classes are

[:alnum:] [:alpha:] [:cntrl:] [:digit:] [:graph:] [:lower:] [:print:] [:punct:] [:space:] [:upper:] [:xdigit:]

Characters can be specified using octal notation, e.g. \012 encodes the newline. Use \173 for the opening curly, \175 for the closing curly, \134 for the backslash, and \036 for the caret if it is the first character in a specification. DON'T use \\, \{, or \} in this case! Hexadecimal notation is written as \x7b (the left curly in this instance).

Result text
The expanded <any> subjected to the tr operator as specified.

Example
The following was entered in interactive mode.

\tr{ {from}{[:lower:][:upper:][:digit:][:space:][:punct:]} {to}{[*L#][*U#][*D#][*S#][*P#]}}{ !"#$%&'()*+,-./0123456789:;<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ [\\]^_` abcdefghijklmnopqrstuvwxyz \{|\}~]} . ---------------------------------------- SSPPPPPPPPPPPPPPPDDDDDDDDDDPPPPPPPSUUUUUUUUUUUUUUUUUUUUUUUUUUSPPPPPPSLLLLLLLLLLLLLLLLLLLLLLLLLLSPPPPP ---------------------------------------- \tr{ {squash}{^} {from}{[:lower:][:upper:][:digit:][:space:][:punct:]} {to}{[*L#][*U#][*D#][*S#][*P#]}}{ !"#$%&'()*+,-./0123456789:;<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ [\\]^_` abcdefghijklmnopqrstuvwxyz \{|\}~]} . ---------------------------------------- SPDPSUSPSLSP

Note how the magic repeat operator [*#] stops on class boundaries.

 
\trace#1:  \trace{<<int>>}

The argument is expanded and interpreted as an integer. This integer encodes an ensemble of flags controlling the trace output. The different modes are exactly the same as those that can be set from the command line. Refer to the corresponding section for more information. Special values are 0 (switch off all tracing), -1 (switch on all tracing modes in short mode), -2 (switch on all tracing modes in long mode), -3 (switch to the previous tracing value), and -4 emit a listing of tracing bits. The third can be useful to switch tracing on for a short while and then off again if you need to debug your document. Additionally and redundantly, \trace#1 puts the previous tracing value in place.

Result text
The previous tracing value.

 
\try#1:  \try{<any>}

This will process the content and output is written in the macro \__zoemput__. Output will be truncated in case \throw#2 was used or an error occurred. The status, currently one of done, towel, or error, is written in the session macro \__zoemstat__.

Result text
None.

 
\undef#1:  \undef{<key-sig>}

Deletes the key with signature <key-sig> from the top level dictionary. Complains (but does not fail) if the key does not exist in that dictionary. It is possible to specify that a regular key (i.e. not a dollar key) must be looked up in the global dictionary by prefixing its signature with two single quotes.

Result text
None.

 
\vanish#1:  \vanish{<any>}

This will only process the content for its side effects. Any result text is disregarded. This allows easy free-style commenting of sequences of definitions. By comparison, \formatted#1 provides the means to give a formatted presentation of the definitions themselves.

Result text
None.

 
\while#2:  \while{<condition>}{<any>}

While <condition> exands to something that is nonzero when interpreted as an integer, <any> is expanded and concatenated to the result text. The following piece of zoem asks the user for an integer and writes all Fibonacci numbers smaller than that integer plus one extra to STDOUT.

\import{ctr.zmm} \: import ctr macros. \def{fib#1}{ \ctrset{a}{1} \ctrset{b}{1} \ctrset{c}{0} \while{\eqt{lq}{\ctrput{c}}{\1}}{ \ctrset{c}{\ctrput{a}} \ctrset{a}{\let{\ctrput{a}+\ctrput{b}}} \write{-}{txt}{\ctrput{c}\|} \ctrset{b}{\ctrset{c}} } } \write{-}{txt}{Enter a number please, } \write{-}{txt}{then press <cr> and <ctl-d>\|} \setx{num}{\finsert{-}} \: this reads from STDIN. \fib{\num}

Note
The strings built up by \while#2 are internally concatenated until it is done, so the result from \while#2 can be captured. This will make \while#2 work for \setx#2. If you want to output 100M worth of lines or paragraphs in a while loop, either embed the stuff to be output in a \write#3 call and make sure that no whitespace results from the loop (for example by using \formatted#1), or simply use \whilst#2. With \write#3 you can specify a file name to which results should be output (use \__fnout__ for the current default output file) whereas \whilst#2 simply outputs to the current default stream.

 
\whilst#2:  \whilst{<condition>}{<any>}

While <condition> exands to something that is nonzero when interpreted as an integer, <any> is expanded and immediately output to the current default output stream.

Result text
None — everything is sent to the default output stream right away. Output from \while#2 can be captured, i.e. it can be that what is assigned by a \setx#2 invocation.

 
\write#3:  \write{<<file name>>}{<str>}{<<any>>}

The first argument is expanded and used as a file name. It is a fatal error if the file has either not been opened by a previous \write#3 call or cannot be opened for writing. Two special file names or 'streams' are recognized, namely - and stderr. They map to STDOUT and STDERR. The third argument is expanded, filtered, and written to file. The second argument indicates the filter to be used. It must be one of the (literal) strings copy, device, or txt.

The copy filter does not filter anything at all (neither plain scope nor device scope) and does not touch any of the zoem escape sequences remaining after expansion.

The device filter does a full-fledged filtering of both parse scopes. It respects the settings according to the \special#1 primitive. The write primitive associates unique metadata with each file it opens, so at directives such as \N, \W, and \+ for different output files do not interfere with one another. Refer to the Device scope section for more information on at directives.

The txt filter maps \\ to \ (i.e. a single backslash), \~ to a single space, \- to a single hyphen, \, (the atomic separator) to nil, \| to a newline, \{ to {, and \} to }. It copies everything else verbatim.

Result text
Technically none, as the output of \write#3 cannot be captured.

 
\writeto#1:  \writeto{<<file-name>>}

Closes the current default output stream, and changes it to point to file <file name>. Useful when splitting a document into chapters, or god forbid, nodes.

Notes
If the file name contains a path separator, zoem will refuse to carry on, because this may pose a risk that sensitive files are overwritten - in case someone has written a malicious zoem input file to do just that. If the option --unsafe is used, zoem will query the user what to do. If the option --unsafe-silent is used, zoem will merrily buzz on without querying. The path separator is entirely UNIX-centric, i.e. a forward slash.

Zoem will recognize if \writeto#1 is issued more than once for the same file <file-name>. On the first occassion, it will simply open the file and truncate any previous contents. On the second occasion and onwards, it will append to the file. There is currently no option to vary this behaviour. Zoem will not recognize the fact that different strings might refer to the same file (e.g. foo and ./foo). Whenever it encounters a file name not seen before, it will try to open the file in write mode.

In interactive mode, \writeto#1 has no effect for text entered in plain mode. It does have effect in case \write#3 is issued with \__fnout__ as the file name argument, since \writeto#3 resets the \__fnout__ macro.

Result text
None.

 
\zinsert#1:  \zinsert{<<file name>>}

The contents of file <file name> are put in place unaltered enclosed by the \!#1 delay primitive. The contents must necessarily satisfy zoem syntax. If the file can not be opened, the empty string results. See also \finsert#1.

Example

\setx{foo}{\zinsert{mydata}} \setx{foo}{\eval{\zinsert{mydata}}}

In the first case, \foo will contain the exact contents of file mydata. Those contents are first enclosed within the \!#1 primitive by \zinsert#1. The resulting text is evaluated by \setx#2 - the only thing this does is strip the enclosing \!{} scope.

In the second case, \foo will contain the evaluated contents of file mydata, as \eval#1 adds an additional layer of evaluation.

Note
This primitive is able to read inline files, unlike \finsert#1.

Result text
The contents of file file name or the empty string if file can not be opened.

Pitfalls

This is a young section, with only few entries yet.

[\system#3] Beware that the argument/option list (the second argument of \system#3) is encoded as a vararg. If you have a single argument, it is easy to forget the enclosing curlies. In that case, zoem ignores the argument altogether.

Zoem protects the data returned by \system#3. So you may e.g. think (as I once did) that

\system{date}{{%e}{%B}{%Y}}

Is a neat way to create a vararg, but you will end up with something like

\{24\}\{April\}\{2004\}
 

[Package authors] Beware of using and scope within at scope within a \write#3 invocation that uses the copy filter.

\write{file}{copy}{ foo \@{ zut \&{ bar }}}

The bar part will not be evaluated as the copy filter does not apply the filtering stage. If the stuff written is read back in from some other part of the document, or from another document altogether, the bar part will be evaluated in a different context than the one in which it was created.

 

\throw#2 with argument done can be used to halt processing of the current file. Refer to the \throw#2 description for the associated requirements.

Glossary

For user keys, dollar keys, and dictionary stacks, refer to the Dictionary stacks section and the Macro expansion section. For data keys, refer to the Tree data section.

For key signatures and key mention, refer to the Key signatures section. For anonymous keys: the Anonymous keys section.

Session variables are described in the Session keys section.

For varargs, arguments in which a variable number of sub-arguments can be stored, and for blocks: the Of blocks and varargs section.

For plain scope, device scope, at scope, and glyph sequences: The Scope dichotomy and Device scope sections.

For file read and inline files: the File read section.

Sometimes zoem protects or unprotects data. Refer to the Protection section.

zoem-11-166/doc/zoem.html0000644000402500021140000012653411576103407012117 00000000000000 zoem

15 Jun 2011    zoem 11-166

NAME

zoem — macro processor for the Zoem macro/programming language.

SYNOPSIS

zoem [-i <file name>[.azm] (entry file name)] [-I <file name> (entry file name)] [-o <file name> (output file name)] [-d <device> (set device key)]

zoem
(enter interactive mode - happens when none of -i, -I, -o is given)

zoem -i <file name>[.azm] (entry file name) -I <file name> (entry file name) [-o <file name> (output file name)] [-d <device> (set device key)] [-x (enter interactive mode on error)] [-s <key>[=<val>] (set key to val)] [-e <any> (evaluate any, exit)] [-E <any> (evaluate any, proceed)] [-chunk-size <num> (process chunks of size num)] [--trace (trace mode, default)] [--trace-all-long (long trace mode)] [--trace-all-short (short trace mode)] [--trace-regex (trace regexes)] [-trace k (trace mode, explicit)] [--stats (show symbol table stats after run)] [--split (assume \writeto usage, set \__split__)] [--stress-write (make \write#3 recover)] [--unsafe (prompt for \system#3)] [--unsafe-silent (simply allow \system#3)] [-allow cmd1[:cmdx]+ (allowable commands)] [--system-honor (require \system#3 to succeed)] [-nuser k (user dict stack size)] [-nenv k (environment dict stack size)] [-nsegment k (maximum simple nesting depth)] [-nstack k (maximum eval nesting depth)] [-buser (initial user dict capacity)] [-bzoem (initial zoem dict capacity)] [-tl k (tab length)] [-l <str> (list items)] [-h (show options)] [--apropos (show options)]

DESCRIPTION

Zoem is a macro/programming language. It is fully described in the Zoem User Manual , currently available in HTML only. This manual page documents the zoem processor, not the zoem language.

If the input file is specified using the -i option and is a regular file (i.e. not STDIN - which is specified by using a single hyphen), it must have the extension .azm. This extension can but need not be specified. The zoem key \__fnbase__ will be set to the file base name stripped of the .azm extension and any leading path components. If the input file is specified using the -I option, no extension is assumed, and \__fnbase__ is set to the file base name, period. The file base name is the file name with any leading path components stripped away.

If neither -i nor -o is specified, zoem enters interactive mode. Zoem should fully recover from any error it encounters in the input. If you find an exception to this rule, consider filing a bug report. In interactive mode, zoem start interpreting once it encounters a line containing a single dot. Zoem's input behaviour can be modified by setting the key \__parmode__. See the section SESSION MACROS for the details. In interactive mode, zoem does not preprocess the interactive input, implying that it does not accept inline files and it does not recognize comments. Both types of sequence will generate syntax errors. Finally, readline editing and history retrieval can be used in interactive mode provided that they are available on the system. This means that the input lines can be retrieved, edited, and discarded with a wide range of cursor positioning and text manipulation commands.

From within the entry file and included files it is possible to open and write to arbitrary files using the \write#3 primitive. Arbitrary files can be read in various modes using the \dofile#2 macro (providing four different modes with respect to file existence and output), \finsert#1, and \zinsert#1. Zoem will write the default output to a single file, the name of which is either specified by the -o option, or constructed as described below. Zoem can split the default output among multiple files. This is governed from within the input files by issuing \writeto#1 calls. Refer to the --split option and the Zoem User Manual.

If none of -i or -o is given, then zoem will enter interactive mode. In this mode, zoem interprets by default chunks of text that are ended by a single dot on a line of its own. This can be useful for testing or debugging. In interactive mode, zoem should recover from any failure it encounters. Interactive mode can also be accessed from within a file by issuing \zinsert{stdia}, and it can be triggered as the mode to enter should an error occur (by adding the -x option to the command line).

If -o is given and -i is not, zoem reads input from STDIN.

If -i is given and -o is not, zoem will construct an output file name as follows. If the -d option was used with argument <dev>, zoem will write to the file which results from expanding \__fnbase__.<dev>. Otherwise, zoem writes to (the expansion of) \__fnbase__.ozm.

For -i and -o, the argument - is interpreted as respectively stdin and stdout.

OPTIONS

-i <file name>[.azm] (entry file name)

Specify the entry file name. The file must have the .azm extension, but it need not be specified.

 
-I <file name>[.azm] (entry file name)

Specify the entry file name, without restrictions on the file name.

 
-o <file name> (output file name)

Specify the output file name.

 
-d <device> (set key \__device__)

Set the key \__device__ to <device>.

 
-x (enter interactive mode on error)

The afterlife option. If zoem encounters an error during regular processing, it will emit error messages as usual, and then enter interactive mode. This allows you e.g. to inspect the values of keys used or defined within the problematic area.

 
-s <key>[=<val>] (set key to val)

Set the key \key to val if present, 1 otherwise. Any type of key can be set, including keys taking arguments and keys surrounded in quotes. Beware of the shell's quote and backslash interpolation. Currently val is not evaluated, so appending or prepending to a key is not possible.

 
-e <any> (evaluate any, exit)

This causes zoem to evaluate <any>, write any result text to stdout, and exit.

 
-E <any> (evaluate any, proceed)

This causes zoem to evaluate <any>, write any result text to stdout, and proceed e.g. with the entry file or an interactive session.

 
-chunk-size <num> (process chunks of size num)

Zoem reads its input in chunks. It fully processes a chunk before moving on with the next one. This option defines the (minimum) size of the chunks. The size or count of the chunks does not at all affect zoem's output. The default minimum chunk size equals one megabyte.

Zoem will read files in their entirety before further processsing if -chunk-size 0 is specified.

Zoem does not chunk input files arbitrarily. It will append to a chunk until it is in the outermost scope (not contained within any block) and the chunk will end with a line that was fully read.

Consequently, if e.g. a file contains a block (delimited by balanced curlies) spanning the entire file then zoem is forced to read it in its entirety.

 
--trace (trace mode, default)

Trace in default mode.

 
--trace-all-long (long trace mode)

Sets on most trace options in long mode. Trace options xxx not set have their own --trace-xxx entry (see below).

 
--trace-all-short (short trace mode)

Sets on most trace options in short mode. Trace options xxx not set have their own --trace-xxx entry (see below).

 
--trace-keys (trace keys)

Trace keys.

 
--trace-regex (trace regexes)

Trace regexes (i.e. the \inspect#4 primitive).

 
-trace k (trace mode, explicit)

Set trace options by adding their representing bits.

 
--stress-write (stress test using write)

This makes \write#3 recover from errors. It is a special purpose option used for creating zoem stress test suites, such as stress.azm in the zoem distribution /examples subdirectory.

 
--unsafe (prompt for \system#3)
--unsafe-silent (simply allow \system#3)
-allow cmd1[:cmdx]+ (allowable commands)

With --unsafe system calls are allowed but the user is prompted for each invocation. The command and its arguments (if any) are shown, but the STDIN information (if any) is withheld. With --unsafe-silent system calls are allowed and the user is never prompted.

Use -allow str or --allow=str to specify a list of allowable commands, as a string in which the commands are separated by colons.

 
--system-honor (require \system#3 to succeed)

With this option any \system#3 failure (for whatever reason, including safe behaviour) is regarded as a zoem failure. By default, failing system calls are ignored under either safe mode, unsafe mode (--unsafe), or silent unsafe mode (--unsafe-silent).

 
--split (assume split output)

This assumes zoem input that allows output to multiple files (e.g. chapters). It sets the default output stream to stdout (anticipating custom output redirection with \writeto#1) and sets the session macro \__split__ to 1.

 
--stats (show symbol table stats after run)

Show symbol table chacteristics. Symbol tables are maintained as hashes.

 
-tl k (set tab length)

Set the tab length. HTML output can be indented according to nesting structure, using tabs which are expanded to simple spaces. By default, the tab length is zero, meaning that no indent is shown. The maximum value the tab length can be set to is four.

 
-nsegment k (level of macro nesting allowed)
-nstack k (stack count)
-nuser k (user dictionary stack size)
-nenv k (environment dictionary stack size)
-buser k (initial user dict capacity)
-bzoem k (initial zoem dict capacity)

Probably needed only if you have some obscure and extreme use for zoem. The segment limit applies to simple nesting of macros. The stack limit applies to nesting of macros that evaluate an argument before use. Each such evaluation creates a new stack. The user limit applies to \push{user}, the env limit applies to the nesting level of environments (started with \begin#2). The user dict capacity pertains to the initial number of buckets allocated for user and environment dictionaries, and the zoem dict capacity pertains to the dictionary containing the zoem primitives.

 
-l <str> (list items)

List items identified by <str>. It can be any of all, filter. legend, builtin, session, trace, or zoem, Multiple identifiers can be joined in a string, e.g. -l legendzoem prints a legend followed by a listing of zoem primitives.

 
-h (show options)

Show short synopsis of options.

SESSION MACROS

\__parmode__
This macro affects zoem's read behaviour in interactive mode. It can be set on the command line using the -s option. Bits that can be set:
1 chomp newlines (remove the newline character) 2 skip empty newlines 4 read paragraphs (an empty line triggers input read) 8 newlines can be escaped using a backslash 16 read large paragraphs (a single dot on a line triggers input read)
\__device__

The current output device, set by the command line option -d. The man and faq packages support html and roff as its values.

\__fnbase__

The base name of the input file name. Leading path components are stripped away. If the -i option is used the input file is required to have the .azm suffix. In that case the suffix is also stripped to obtain the base name.

\__fnentry__

The name of the entry file.

\__fnin__

The file currently being processed.

\__fnout__

The name of the default output file.

\__fnpath__

The leading component of the input file name, possibly empty.

\__fnup__

The file that included the current file, if applicable.

\__fnwrite__

This key is set by \write#3 to its first argument. It can be used by macros that are expanded during evaluation of the third argument. Possible usage is to branch on the name of the write output stream. For example a file called index.html may be treated differently from other files. The key is deleted afterwards. Nested invocations of \write#3 may corrupt the status of this key.

\__ia__

The input/output separator used in interactive mode.

\__line__

The line number in the file currently being processed. This number will be correct for any invocation outside the scope of a macro. For any invocation within a macro the result will be the line number of the closing curly of the outermost containing macro. The following

\__line__ \__line__ \__line__ \group{ \__line__ \group{\__line__} \__line__}

Results in

1 2 3 7 7 7
\__searchpath__

A vararg containing a list of paths to search when a file is to be included/imported/read/loaded. When you start zoem, this key should contain the location of the man.zmm and faq.zmm package files. It is advisable not to overwrite this key but to append to it instead.

\__zoemstat__

Set to one of ok, towel (that one is a bit lame), or error by either the interpreter, an occurrence of \catch#2, or \try#1.

\__zoemput__

Set by \try#1 to the possibly truncated result of processing its argument.

\__lc__

Expands to a left curly. It is hard to find a need for this — the zoem stress suite uses it to generate a particular syntax error at a deeper interpretation level.

\__rc__

Expands to a right curly.

THE SET MODIFIERS

The \set#3 primitive allows a {modes}{<modifiers>} directive in its first argument. Here <modifiers> can be a combination of single-letter modifiers, each described below.

a

append to the key, do not overwrite, create if not existing.

c

conditionally; only set if not already defined.

e

existing; update existing key, possibly in lower dictionary.

g

global; set in the global (bottom) user dictionary.

u

unary; do not interpret vararg in <any> as key-value list (data keys only)

v

vararg; interpret vararg in <any> as key-value list (regular keys only).

w

warn if key exists (like \def#2 and \defx#2).

x

expand argument (like \setx#2 and \defx#2).

THE INSPECT SUBLANGUAGE

The \inspect#4 primitive takes four arguments. The languages accepted by the first two arguments are described below. The third argument is a replacement string or a replacement macro accepting back-references (supplied as an anonymous macro). The fourth argument is the data to be processed.

arg 1
Is a vararg. Currently it accepts a single key mods for which the value should be a comma-separated list over the words posix, icase, dotall, iter-lines iter-args, match-once, discard-nmp, discard-nil-out, discard-miss, count-matches. Alternatively repeated use of mods is allowed.

arg 2
Is a regular expression. Tilde patterns are expanded according to all of the ZOEM, UNIX, and REGEX schemes. Refer to TILDE EXPANSION for these.

The third argument is a constant string or an anonymous key, the fourth argument is data.

THE TR SUBLANGUAGE

The \tr#2 primitive takes two arguments. The first argument contains key-value pairs. The accepted keys are from and to which must always occur together, and delete and squash. The values of these keys must be valid translation specifications. This primitive transforms the data in the second argument by successively applying translation, deletion and squashing in that order. Only the transformations that are needed need be specified.

Translation specifications are subjected to UNIX tilde expansion as described below.

The syntax accepted by translation specifications is almost fully compliant with the syntax accepted by tr(1), with three exceptions. First, repeats are introduced as [*a*20] rather than [a*20]. Second, ranges can (for now) only be entered as X-Y, not as [X-Y]. X and Y can be entered in either octal or hexadecimal notation (see further below). As an additional feature, the magic repeat operator [*a#] stops on both class and range boundaries. Character specifications can be complemented by preceding them with the caret ^.

Specifications may contain ranges of characters such as a-z and 0-9. Posix character classes are allowed. The available classes are

[:alnum:] [:alpha:] [:cntrl:] [:digit:] [:graph:] [:lower:] [:print:] [:punct:] [:space:] [:upper:] [:xdigit:]

Characters can be specified using octal notation, e.g. \012 encodes the newline. Use \173 for the opening curly, \175 for the closing curly, \134 for the backslash, and \036 for the caret if it is the first character in a specification. DON'T use \\, \{, or \} in this case! Hexadecimal notation is written as \x7b (the left curly in this instance).

See EXAMPLES for an example of tr#2 usage.

TILDE EXPANSION

Some primitives interface with UNIX libraries that require backslash escape sequences to encode certain tokens or characters. The backslash is special in zoem too and without further measures it can become very cumbersome to encode the correct escape sequences as it is not always clear which tokens should be escaped or unprotected at what point. It is especially difficult to handle the zoem characters with special meaning, {, } and \.

The two primitives under consideration are \inspect#4 and \tr#2. Both treat the tilde as an additional escape character for certain arguments (as documented in the user manual). These arguments are subjected to tilde expansion, where the tilde and the character it proceeds are translated to a new character or character sequence. There are three different sets of tilde escapes, ZOEM, UNIX and REGEX escapes. \tr#2 only accepts UNIX escapes, \inspect#4 accepts all. Tilde expansion is always the last processing step before strings are passed on to external libraries.

The ZOEM scheme contains some convenience escapes, such as ~E to encode a double backslash.

ZOEM tilde expansion

meta sequence replacement .-----------------------------. | ~~ | ~ | | ~E | \\ | | ~e | \ | | ~I | \{ | | ~J | \} | | ~x | \x | | ~i | { | | ~j | } | `-----------------------------'

The zoem tr specification language accepts \x** as hexadecimal notation, e.g. \x0a denotes a newline in the ASCII character set

.

UNIX tilde expansion

meta sequence replacement .-----------------------------. | ~a | \a | | ~b | \b | | ~f | \f | | ~n | \n | | ~r | \r | | ~t | \t | | ~v | \v | | ~0 | \0 | | ~1 | \1 | | ~2 | \2 | | ~3 | \3 | `-----------------------------'

REGEX tilde expansion

meta sequence replacement .-----------------------------. | ~^ | \^ | | ~. | \. | | ~[ | \[ | | ~$ | \$ | | ~( | \( | | ~) | \) | | ~| | \| | | ~* | \* | | ~+ | \+ | | ~? | \? | `-----------------------------'

ENVIRONMENT

The environment variable ZOEMSEARCHPATH may contain a colon and/or whitespace separated list of paths. It will be used when searching for files included via one of the dofile aliases \input, \import, \read, and \load. Note that the zoem macro \__searchpath__ contains the location where the zoem macro files were copied at the time of installation of zoem.

DIAGNOSTICS

On error, Zoem prints a file name and a line number to which it was able to trace the error. The number reported is the same as the one stored in the session macro \__line__. For an error-trigering macro which is not nested within another macro the line number should be correct. For a macro that does occur nested within another macro the line number will be the line number of the closing curly in the outermost containing macro.

If in despair, use one of the tracing modes, --trace-keys is one of the first to come to mind. Another possibility is to supply the -x option.

BUGS

No known bugs. \inspect#4 has not received thorough stress-testing, and the more esoteric parts of its interface will probably change.

SEE ALSO

Aephea is a document authoring framework largely for HTML documents.

Portable Unix Documentation provides two mini-languages for authoring in the unix environment. These languages, pud-man and pud-faq are both written in zoem.

EXAMPLES

This is a relatively new section, aimed at assembling useful or explanatory snippets.

Create a vararg containing file names matching a pattern (png in this example).

\setx{images}{ \inspect{ {mods}{iter-lines,discard-miss} }{(.*~.png)}{_#1{{\1}}}{\system{ls}} }

Use magic boundary stops with tr#2.

\tr{ {from}{[:lower:][:upper:][:digit:][:space:][:punct:]} {to}{[*L#][*U#][*D#][*S#][*P#]}}{ !"#$%&'()*+,-./0123456789:;<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ [\\]^_` abcdefghijklmnopqrstuvwxyz \{|\}~]}

AUTHOR

Stijn van Dongen.

zoem-11-166/doc/zoem.ps0000644000402500021140000020442311576103407011567 00000000000000%!PS-Adobe-3.0 %%Creator: groff version 1.18.1.1 %%CreationDate: Wed Jun 15 11:18:47 2011 %%DocumentNeededResources: font Times-Roman %%+ font Times-Bold %%+ font Times-Italic %%+ font Courier %%DocumentSuppliedResources: procset grops 1.18 1 %%Pages: 9 %%PageOrder: Ascend %%Orientation: Portrait %%EndComments %%BeginProlog %%BeginResource: procset grops 1.18 1 /setpacking where{ pop currentpacking true setpacking }if /grops 120 dict dup begin /SC 32 def /A/show load def /B{0 SC 3 -1 roll widthshow}bind def /C{0 exch ashow}bind def /D{0 exch 0 SC 5 2 roll awidthshow}bind def /E{0 rmoveto show}bind def /F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def /G{0 rmoveto 0 exch ashow}bind def /H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /I{0 exch rmoveto show}bind def /J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def /K{0 exch rmoveto 0 exch ashow}bind def /L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /M{rmoveto show}bind def /N{rmoveto 0 SC 3 -1 roll widthshow}bind def /O{rmoveto 0 exch ashow}bind def /P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def /Q{moveto show}bind def /R{moveto 0 SC 3 -1 roll widthshow}bind def /S{moveto 0 exch ashow}bind def /T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def /SF{ findfont exch [exch dup 0 exch 0 exch neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /MF{ findfont [5 2 roll 0 3 1 roll neg 0 0]makefont dup setfont [exch/setfont cvx]cvx bind def }bind def /level0 0 def /RES 0 def /PL 0 def /LS 0 def /MANUAL{ statusdict begin/manualfeed true store end }bind def /PLG{ gsave newpath clippath pathbbox grestore exch pop add exch pop }bind def /BP{ /level0 save def 1 setlinecap 1 setlinejoin 72 RES div dup scale LS{ 90 rotate }{ 0 PL translate }ifelse 1 -1 scale }bind def /EP{ level0 restore showpage }bind def /DA{ newpath arcn stroke }bind def /SN{ transform .25 sub exch .25 sub exch round .25 add exch round .25 add exch itransform }bind def /DL{ SN moveto SN lineto stroke }bind def /DC{ newpath 0 360 arc closepath }bind def /TM matrix def /DE{ TM currentmatrix pop translate scale newpath 0 0 .5 0 360 arc closepath TM setmatrix }bind def /RC/rcurveto load def /RL/rlineto load def /ST/stroke load def /MT/moveto load def /CL/closepath load def /Fr{ setrgbcolor fill }bind def /Fk{ setcmykcolor fill }bind def /Fg{ setgray fill }bind def /FL/fill load def /LW/setlinewidth load def /Cr/setrgbcolor load def /Ck/setcmykcolor load def /Cg/setgray load def /RE{ findfont dup maxlength 1 index/FontName known not{1 add}if dict begin { 1 index/FID ne{def}{pop pop}ifelse }forall /Encoding exch def dup/FontName exch def currentdict end definefont pop }bind def /DEFS 0 def /EBEGIN{ moveto DEFS begin }bind def /EEND/end load def /CNT 0 def /level1 0 def /PBEGIN{ /level1 save def translate div 3 1 roll div exch scale neg exch neg exch translate 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit []0 setdash /setstrokeadjust where{ pop false setstrokeadjust }if /setoverprint where{ pop false setoverprint }if newpath /CNT countdictstack def userdict begin /showpage{}def }bind def /PEND{ clear countdictstack CNT sub{end}repeat level1 restore }bind def end def /setpacking where{ pop setpacking }if %%EndResource %%IncludeResource: font Times-Roman %%IncludeResource: font Times-Bold %%IncludeResource: font Times-Italic %%IncludeResource: font Courier grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron /scaron/zcaron/Ydieresis/trademark/quotesingle/Euro/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef /.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent /ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen /period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon /semicolon/less/equal/greater/question/at/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/bracketleft/backslash/bracketright/circumflex /underscore/quoteleft/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/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft /guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl /endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut /dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash /quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen /brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft /logicalnot/minus/registered/macron/degree/plusminus/twosuperior /threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior /ordmasculine/guilsinglright/onequarter/onehalf/threequarters /questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE /Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex /Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis /multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn /germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla /egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis /eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash /ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def /Courier@0 ENC0/Courier RE/Times-Italic@0 ENC0/Times-Italic RE /Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE %%EndProlog %%Page: 1 1 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 153.455<7a6f656d2831292055534552>20 48 R 155.955 <434f4d4d414e4453207a6f656d283129>2.5 F 7.5<312e204e>42.5 84 R<414d45> -.35 E 7.5<322e2053594e4f50534953>42.5 96 R 7.5 <332e204445534352495054494f4e>42.5 108 R 7.5<342e204f5054494f4e53>42.5 120 R 7.5<352e2053455353494f4e>42.5 132 R<4d41>2.5 E<4352>-.4 E<4f53>-.4 E 7.5<362e20544845>42.5 144 R<534554204d4f44494649455253>2.5 E 7.5 <372e20544845>42.5 156 R<494e5350454354205355424c414e4755>2.5 E -.4 <4147>-.4 G<45>.4 E 7.5<382e20544845>42.5 168 R<5452205355424c414e4755> 2.5 E -.4<4147>-.4 G<45>.4 E 7.5<392e2054494c4445>42.5 180 R<455850>2.5 E<414e53494f4e>-.92 E 7.5<31302e20454e564952>37.5 192 R<4f4e4d454e54>-.4 E 7.5<31312e20444941>37.5 204 R<474e4f5354494353>-.4 E 7.5<31322e2042> 37.5 216 R<554753>-.1 E 7.5<31332e20534545>37.5 228 R<414c534f>2.5 E 7.5 <31342e204558414d504c4553>37.5 240 R 7.5<31352e2041>37.5 252 R <5554484f52>-.55 E/F1 10.95/Times-Bold@0 SF -.219<4e41>20 268.8 S<4d45> .219 E F0<7a6f656d20ad206d6163726f2070726f636573736f7220666f722074686520 5a6f656d206d6163726f2f70726f6772616d6d696e67206c616e67756167652e>100 280.8 Q F1<53594e4f50534953>20 297.6 Q/F2 10/Times-Bold@0 SF .322 <7a6f656d205b2d69>100 309.6 R F0 .322 <3c8c6c65206e616d653e5b2e617a6d5d2028>2.822 F/F3 10/Times-Italic@0 SF .322<656e747279208c6c65206e616d65>B F0<29>A F2 2.821<5d5b>C<2d49>-2.821 E F0 .321<3c8c6c65206e616d653e2028>2.821 F F3 .321 <656e747279208c6c65206e616d65>B F0<29>A F2 2.821<5d5b>C<2d6f>-2.821 E F0 .321<3c8c6c65206e616d653e>2.821 F<28>100 321.6 Q F3 <6f7574707574208c6c65206e616d65>A F0<29>A F2 2.5<5d5b>C<2d64>-2.5 E F0 <3c6465>2.5 E<766963653e2028>-.25 E F3<736574206465>A<76696365206b>-.15 E -.3<6579>-.1 G F0<29>.3 E F2<5d>A<7a6f656d>100 345.6 Q F0 <28656e74657220696e74657261637469>100 357.6 Q .3 -.15<7665206d>-.25 H <6f6465202d2068617070656e73207768656e206e6f6e65206f66>.15 E F2<2d69>2.5 E F0<2c>A F2<2d49>2.5 E F0<2c>A F2<2d6f>2.5 E F0<6973206769>2.5 E -.15 <7665>-.25 G<6e29>.15 E F2 1.209<7a6f656d202d69>100 381.6 R F0 1.209 <3c8c6c65206e616d653e5b2e617a6d5d2028>3.709 F F3 1.209 <656e747279208c6c65206e616d65>B F0<29>A F2<2d49>3.709 E F0 1.209 <3c8c6c65206e616d653e2028>3.709 F F3 1.21<656e747279208c6c65206e616d65>B F0<29>A F2<5b2d6f>3.71 E F0 1.21<3c8c6c65206e616d653e>3.71 F<28>100 393.6 Q F3 1.938<6f7574707574208c6c65206e616d65>B F0<29>A F2 4.437<5d5b> C<2d64>-4.437 E F0<3c6465>4.437 E 1.937<766963653e2028>-.25 F F3 1.937 <736574206465>B 1.937<76696365206b>-.15 F -.3<6579>-.1 G F0<29>.3 E F2 4.437<5d5b>C<2d78>-4.437 E F0<28>4.437 E F3 1.937 <656e74657220696e746572>B 1.937<616374697665206d6f6465206f6e20657272> -.15 F<6f72>-.45 E F0<29>A F2 4.437<5d5b>C<2d73>-4.437 E F0<3c6b>100 405.6 Q -.15<6579>-.1 G<3e5b3d3c76>.15 E 1.272<616c3e5d2028>-.25 F F3 1.272<736574206b>B 1.873 -.3<65792074>-.1 H 3.773<6f76>.3 G<616c>-3.773 E F0<29>A F2 3.773<5d5b>C<2d65>-3.773 E F0<3c616e>3.773 E 1.273 <793e2028>-.15 F F3 -.15<6576>C 1.273<616c7561746520616e79>.15 F 3.773 <2c65>-.55 G<786974>-3.973 E F0<29>A F2 3.773<5d5b>C<2d45>-3.773 E F0 <3c616e>3.773 E 1.273<793e2028>-.15 F F3 -.15<6576>C 1.273 <616c7561746520616e79>.15 F 3.773<2c70>-.55 G -.45<726f>-3.773 G<2d>.45 E<63656564>100 417.6 Q F0<29>A F2 5.47<5d5b>C<2d6368756e6b2d73697a65> -5.47 E F0 2.969<3c6e756d3e2028>5.469 F F3<7072>A 2.969<6f636573732063> -.45 F 2.969<68756e6b73206f662073697a65206e756d>-.15 F F0<29>A F2 5.469 <5d5b>C<2d2d7472616365>-5.469 E F0<28>5.469 E F3<7472>A 2.969 <616365206d6f6465>-.15 F 5.469<2c64>-.1 G<656661756c74>-5.469 E F0<29>A F2<5d>A<5b2d2d74726163652d616c6c2d6c6f6e67>100 429.6 Q F0<28>2.826 E F3 .326<6c6f6e67207472>B .326<616365206d6f6465>-.15 F F0<29>A F2 2.827 <5d5b>C<2d2d74726163652d616c6c2d73686f7274>-2.827 E F0<28>2.827 E F3 .327<73686f7274207472>B .327<616365206d6f6465>-.15 F F0<29>A F2 2.827 <5d5b>C<2d2d74726163652d72>-2.827 E<65676578>-.18 E F0<28>2.827 E F3 <7472>A<616365>-.15 E -.37<7265>100 441.6 S -.1<6765>-.03 G<786573>-.1 E F0<29>A F2 3.624<5d5b>C<2d7472616365>-3.624 E F0 3.624<6b28>3.624 G F3 <7472>-3.624 E 1.124<616365206d6f6465>-.15 F 3.624<2c65>-.1 G <78706c69636974>-3.824 E F0<29>A F2 3.624<5d5b>C<2d2d7374617473>-3.624 E F0<28>3.624 E F3 1.124 <73686f772073796d626f6c207461626c652073746174732061667465722072756e>B F0 <29>A F2 3.623<5d5b>C<2d2d73706c6974>-3.623 E F0<28>100 453.6 Q F3 2.988 <617373756d65205c7772697465746f20757361>B 3.189 -.1<67652c2073>-.1 H 2.989<6574205c5f5f73706c69745f5f>.1 F F0<29>A F2 5.489<5d5b>C <2d2d737472>-5.489 E<6573732d7772697465>-.18 E F0<28>5.489 E F3<6d616b>A 5.489<655c>-.1 G 2.989<777269746523332072>-5.489 F<65636f>-.37 E<766572> -.1 E F0<29>A F2 5.489<5d5b>C<2d2d756e73616665>-5.489 E F0<28>100 465.6 Q F3<7072>A 3.494<6f6d707420666f72205c73797374656d2333>-.45 F F0<29>A F2 5.994<5d5b>C<2d2d756e736166652d73696c656e74>-5.994 E F0<28>5.994 E F3 3.494<73696d706c7920616c6c6f77205c73797374656d2333>B F0<29>A F2 5.993 <5d5b>C<2d616c6c6f>-5.993 E<77>-.1 E F0<636d64315b3a636d64785d2b>5.993 E <28>100 477.6 Q F3 1.437<616c6c6f7761626c6520636f6d6d616e6473>B F0<29>A F2 3.937<5d5b>C<2d2d73797374656d2d686f6e6f72>-3.937 E F0<28>3.937 E F3 -.37<7265>C<71756972>.37 E 3.937<655c>-.37 G 1.437 <73797374656d233320746f2073756363656564>-3.937 F F0<29>A F2 3.937<5d5b>C <2d6e75736572>-3.937 E F0 3.937<6b28>3.937 G F3 1.437 <757365722064696374>-3.937 F<73746163>100 489.6 Q 4.606<6b73>-.2 G <697a65>-4.606 E F0<29>A F2 4.606<5d5b>C<2d6e656e>-4.606 E<76>-.4 E F0 4.606<6b28>4.606 G F3<656e>-4.606 E<766972>-.4 E 2.106 <6f6e6d656e7420646963742073746163>-.45 F 4.606<6b73>-.2 G<697a65>-4.606 E F0<29>A F2 4.606<5d5b>C<2d6e7365676d656e74>-4.606 E F0 4.606<6b28> 4.606 G F3 2.105<6d6178696d756d2073696d706c65206e657374696e67>-4.606 F <6465707468>100 501.6 Q F0<29>A F2 3.201<5d5b>C<2d6e737461636b>-3.201 E F0 3.201<6b28>3.201 G F3 .701<6d6178696d756d2065>-3.201 F .702 <76616c206e657374696e67206465707468>-.15 F F0<29>A F2 3.202<5d5b>C<2d62> -3.202 E<75736572>-.2 E F0<28>3.202 E F3 .702 <696e697469616c20757365722064696374206361706163697479>B F0<29>A F2 3.202 <5d5b>C<2d627a6f656d>-3.202 E F0<28>100 513.6 Q F3 .149 <696e697469616c207a6f656d2064696374206361706163697479>B F0<29>A F2 2.649 <5d5b>C<2d746c>-2.649 E F0 2.649<6b28>2.649 G F3 .149 <746162206c656e677468>-2.649 F F0<29>A F2 2.649<5d5b>C<2d6c>-2.649 E F0 .149<3c7374723e2028>2.649 F F3 .148<6c697374206974656d73>B F0<29>A F2 2.648<5d5b>C<2d68>-2.648 E F0<28>2.648 E F3 .148 <73686f77206f7074696f6e73>B F0<29>A F2 2.648<5d5b>C<2d2d617072>-2.648 E <6f2d>-.18 E<706f73>100 525.6 Q F0<28>2.5 E F3<73686f77206f7074696f6e73> A F0<29>A F2<5d>A F1<4445534352495054494f4e>20 542.4 Q F0 2.884<5a6f656d 2069732061206d6163726f2f70726f6772616d6d696e67206c616e67756167652e204974 2069732066756c6c792064657363726962656420696e20746865>100 554.4 R F3 2.884<5a6f656d2055736572204d616e75616c>5.384 F F0 .825 <287a756d2e68746d6c292c2063757272656e746c792061>100 566.4 R -.25<7661> -.2 G .825<696c61626c6520696e2048544d4c206f6e6c792e2054686973206d616e75 616c207061676520646f63756d656e747320746865207a6f656d2070726f6365732d>.25 F<736f72>100 578.4 Q 2.5<2c6e>-.4 G <6f7420746865207a6f656d206c616e67756167652e>-2.5 E .964<4966207468652069 6e707574208c6c652069732073706563698c6564207573696e6720746865>100 602.4 R F2<2d69>3.464 E F0 .965<6f7074696f6e20616e642069732061207265>3.464 F .965<67756c6172208c6c652028692e652e206e6f7420535444494e202d207768696368 206973>-.15 F 1.125 <73706563698c6564206279207573696e6720612073696e676c652068>100 614.4 R 1.125<797068656e292c206974206d757374206861>-.05 F 1.425 -.15<76652074> -.2 H 1.125<68652065>.15 F<7874656e73696f6e>-.15 E/F4 10/Courier@0 SF <2e617a6d>3.624 E F0 3.624<2e54>C 1.124<6869732065>-3.624 F 1.124 <7874656e73696f6e2063616e2062>-.15 F<7574>-.2 E .044 <6e656564206e6f742062652073706563698c65642e20546865207a6f656d206b>100 626.4 R -.15<6579>-.1 G F2<5c5f5f666e626173655f5f>2.694 E F0 .045<77696c 6c2062652073657420746f20746865208c6c652062617365206e616d6520737472697070 6564206f6620746865>2.544 F F4<2e617a6d>100 638.4 Q F0 -.15<6578>4.104 G 1.604<74656e73696f6e20616e6420616e>.15 F 4.104<796c>-.15 G 1.604 <656164696e67207061746820636f6d706f6e656e74732e>-4.104 F 1.603<49662074 686520696e707574208c6c652069732073706563698c6564207573696e6720746865> 6.603 F F2<2d49>4.103 E F0 .892<6f7074696f6e2c206e6f2065>100 650.4 R .892<7874656e73696f6e20697320617373756d65642c20616e64>-.15 F F2 <5c5f5f666e626173655f5f>3.392 E F0 .893<69732073657420746f20746865208c6c 652062617365206e616d652c20706572696f642e20546865208c6c65>3.392 F <62617365206e616d6520697320746865208c6c65206e616d65207769746820616e>100 662.4 Q 2.5<796c>-.15 G <656164696e67207061746820636f6d706f6e656e74732073747269707065642061>-2.5 E -.1<7761>-.15 G<792e>.1 E .9<4966206e656974686572>100 686.4 R F2<2d69> 3.4 E F0<6e6f72>3.4 E F2<2d6f>3.4 E F0 .9 <69732073706563698c65642c207a6f656d20656e7465727320696e74657261637469> 3.4 F 1.2 -.15<7665206d>-.25 H .9 <6f64652e205a6f656d2073686f756c642066756c6c79207265636f>.15 F -.15<7665> -.15 G 3.4<7266>.15 G<726f6d>-3.4 E<616e>100 698.4 Q 3.329<7965>-.15 G .829<72726f7220697420656e636f756e7465727320696e2074686520696e7075742e> -3.329 F .829<496620796f75208c6e6420616e2065>5.829 F .83<7863657074696f 6e20746f20746869732072756c652c20636f6e7369646572208c6c696e6720612062> -.15 F<7567>-.2 E .605<7265706f72742e20496e20696e74657261637469>100 710.4 R .905 -.15<7665206d>-.25 H .605<6f64652c207a6f656d20737461727420 696e74657270726574696e67206f6e636520697420656e636f756e746572732061206c69 6e6520636f6e7461696e696e6720612073696e676c65>.15 F .486 <646f742e205a6f656d27>100 722.4 R 2.986<7369>-.55 G .486 <6e7075742062656861>-2.986 F .486<76696f75722063616e206265206d6f64698c65 642062792073657474696e6720746865206b>-.2 F -.15<6579>-.1 G F2 <5c5f5f7061726d6f64655f5f>3.137 E F0 2.987<2e53>C .487 <6565207468652073656374696f6e>-2.987 F<7a6f656d2031312d313636>20 768 Q <3135204a756e2032303131>157.065 E<31>204.555 E 0 Cg EP %%Page: 2 2 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 153.455<7a6f656d2831292055534552>20 48 R 155.955 <434f4d4d414e4453207a6f656d283129>2.5 F/F1 10/Times-Bold@0 SF .118 <53455353494f4e204d41>100 84 R<4352>-.55 E<4f53>-.3 E F0 .118 <666f72207468652064657461696c732e>2.618 F .118<496e20696e74657261637469> 5.118 F .418 -.15<7665206d>-.25 H .118<6f64652c207a6f656d20646f6573>.15 F/F2 10/Times-Italic@0 SF<6e6f74>2.617 E F0 .117 <70726570726f636573732074686520696e74657261632d>2.617 F<7469>100 96 Q .582 -.15<76652069>-.25 H .283<6e7075742c20696d706c79696e67207468617420 697420646f6573206e6f742061636365707420696e6c696e65208c6c657320616e642069 7420646f6573206e6f74207265636f676e697a6520636f6d6d656e74732e20426f7468> .15 F .496<7479706573206f662073657175656e63652077696c6c2067656e65726174 652073796e746178206572726f72732e>100 108 R<46696e616c6c79>5.496 E 2.996 <2c72>-.65 G .496 <6561646c696e652065646974696e6720616e6420686973746f727920726574726965> -2.996 F -.25<7661>-.25 G 2.996<6c63>.25 G<616e>-2.996 E .627 <6265207573656420696e20696e74657261637469>100 120 R .927 -.15<7665206d> -.25 H .627<6f64652070726f>.15 F .627<7669646564207468617420746865>-.15 F 3.127<7961>-.15 G .628<72652061>-3.127 F -.25<7661>-.2 G .628<696c6162 6c65206f6e207468652073797374656d2e2054686973206d65616e732074686174207468 65>.25 F .917<696e707574206c696e65732063616e20626520726574726965>100 132 R -.15<7665>-.25 G .917<642c206564697465642c20616e6420646973636172646564 2077697468206120776964652072616e6765206f6620637572736f7220706f736974696f 6e696e6720616e64>.15 F<7465>100 144 Q <7874206d616e6970756c6174696f6e20636f6d6d616e64732e>-.15 E 1.239<46726f 6d2077697468696e2074686520656e747279208c6c6520616e6420696e636c7564656420 8c6c657320697420697320706f737369626c6520746f206f70656e20616e642077726974 6520746f20617262697472617279208c6c6573>100 168 R 1.275 <7573696e6720746865>100 180 R F1<5c77726974652333>3.775 E F0 <7072696d697469>3.775 E -.15<7665>-.25 G 3.775<2e41>.15 G 1.275 <7262697472617279208c6c65732063616e206265207265616420696e2076>-3.775 F 1.275<6172696f7573206d6f646573207573696e6720746865>-.25 F F1 <5c646f8c6c652332>3.775 E F0 .384<6d6163726f202870726f>100 192 R .384 <766964696e6720666f757220646966>-.15 F .385 <666572656e74206d6f6465732077697468207265737065637420746f208c6c652065> -.25 F .385<78697374656e636520616e64206f7574707574292c>-.15 F F1 <5c8c6e736572742331>2.885 E F0 2.885<2c61>C<6e64>-2.885 E F1 <5c7a696e736572742331>100 204 Q F0 5.153<2e5a>C .153 <6f656d2077696c6c2077726974652074686520646566>-5.153 F .152<61756c74206f 757470757420746f20612073696e676c65208c6c652c20746865206e616d65206f662077 68696368206973206569746865722073706563692d>-.1 F 1.948 <8c656420627920746865>100 216 R F1<2d6f>4.448 E F0 1.949<6f7074696f6e2c 206f7220636f6e7374727563746564206173206465736372696265642062656c6f>4.448 F 1.949<772e205a6f656d2063616e2073706c69742074686520646566>-.25 F 1.949 <61756c74206f7574707574>-.1 F 1.07 <616d6f6e67206d756c7469706c65208c6c65732e205468697320697320676f>100 228 R -.15<7665>-.15 G 1.069<726e65642066726f6d2077697468696e2074686520696e 707574208c6c65732062792069737375696e67>.15 F F1<5c7772697465746f2331> 3.569 E F0<63616c6c732e>3.569 E<526566657220746f20746865>100 240 Q F1 <2d2d73706c6974>2.5 E F0<6f7074696f6e20616e6420746865>2.5 E F2 <5a6f656d2055736572204d616e75616c>2.5 E F0<2e>A .384 <4966206e6f6e65206f66>100 264 R F1<2d69>2.884 E F0<6f72>2.884 E F1<2d6f> 2.884 E F0 .384<6973206769>2.884 F -.15<7665>-.25 G .384 <6e2c207468656e207a6f656d2077696c6c20656e74657220696e74657261637469>.15 F .685 -.15<7665206d>-.25 H .385 <6f64652e20496e2074686973206d6f64652c207a6f656d20696e7465727072657473> .15 F .567<627920646566>100 276 R .567 <61756c74206368756e6b73206f66207465>-.1 F .566<787420746861742061726520 656e64656420627920612073696e676c6520646f74206f6e2061206c696e65206f662069 7473206f>-.15 F .566<776e2e20546869732063616e2062652075736566756c>-.25 F .817<666f722074657374696e67206f7220646562>100 288 R .818 <756767696e672e20496e20696e74657261637469>-.2 F 1.118 -.15<7665206d>-.25 H .818<6f64652c207a6f656d2073686f756c64207265636f>.15 F -.15<7665>-.15 G 3.318<7266>.15 G .818<726f6d20616e>-3.318 F 3.318<7966>-.15 G .818 <61696c75726520697420656e636f756e2d>-3.418 F .501 <746572732e20496e74657261637469>100 300 R .801 -.15<7665206d>-.25 H .501 <6f64652063616e20616c736f2062652061636365737365642066726f6d207769746869 6e2061208c6c652062792069737375696e67>.15 F/F3 10/Courier@0 SF <5c7a696e736572747b73746469617d>3 E F0<2c>A .181<616e642069742063616e20 62652074726967676572656420617320746865206d6f646520746f20656e746572207368 6f756c6420616e206572726f72206f636375722028627920616464696e6720746865>100 312 R F1<2d78>2.682 E F0 .182<6f7074696f6e20746f20746865>2.682 F <636f6d6d616e64206c696e65292e>100 324 Q<4966>100 348 Q F1<2d6f>2.5 E F0 <6973206769>2.5 E -.15<7665>-.25 G 2.5<6e61>.15 G<6e64>-2.5 E F1<2d69> 2.5 E F0<6973206e6f742c207a6f656d20726561647320696e7075742066726f6d2053 5444494e2e>2.5 E<4966>100 372 Q F1<2d69>3.24 E F0 .74<6973206769>3.24 F -.15<7665>-.25 G 3.24<6e61>.15 G<6e64>-3.24 E F1<2d6f>3.24 E F0 .739<69 73206e6f742c207a6f656d2077696c6c20636f6e73747275637420616e206f7574707574 208c6c65206e616d6520617320666f6c6c6f>3.24 F .739<77732e20496620746865> -.25 F F1<2d64>3.239 E F0<6f7074696f6e>3.239 E -.1<7761>100 384 S 4.592 <7375>.1 G 2.092<7365642077697468206172>-4.592 F<67756d656e74>-.18 E F3 <3c6465763e>4.593 E F0 4.593<2c7a>C 2.093<6f656d2077696c6c20777269746520 746f20746865208c6c6520776869636820726573756c74732066726f6d2065>-4.593 F <7870616e64696e67>-.15 E F1<5c5f5f666e626173655f5f2e3c6465>100 396 Q <763e>-.15 E F0 2.5<2e4f>C <74686572776973652c207a6f656d2077726974657320746f20287468652065>-2.5 E <7870616e73696f6e206f6629>-.15 E F1<5c5f5f666e626173655f5f2e6f7a6d>2.5 E F0<2e>A -.15<466f>100 420 S<72>.15 E F1<2d69>2.5 E F0<616e64>2.5 E F1 <2d6f>2.5 E F0 2.5<2c74>C<6865206172>-2.5 E<67756d656e74>-.18 E F3<2d> 2.5 E F0<697320696e746572707265746564206173207265737065637469>2.5 E -.15 <7665>-.25 G<6c79>.15 E F3<737464696e>2.5 E F0<616e64>2.5 E F3 <7374646f7574>2.5 E F0<2e>A/F4 10.95/Times-Bold@0 SF<4f5054494f4e53>20 436.8 Q F1<2d69>100 448.8 Q F0<3c8c6c65206e616d653e5b2e617a6d5d2028>2.5 E F2<656e747279208c6c65206e616d65>A F0<29>A .1<537065636966792074686520 656e747279208c6c65206e616d652e20546865208c6c65206d757374206861>120 460.8 R .399 -.15<76652074>-.2 H<6865>.15 E F3<2e617a6d>2.599 E F0 -.15<6578> 2.599 G .099<74656e73696f6e2c2062>.15 F .099 <7574206974206e656564206e6f7420626520737065632d>-.2 F<698c65642e>120 472.8 Q F1<2d49>100 496.8 Q F0<3c8c6c65206e616d653e5b2e617a6d5d2028>2.5 E F2<656e747279208c6c65206e616d65>A F0<29>A<537065636966792074686520656e 747279208c6c65206e616d652c20776974686f7574207265737472696374696f6e73206f 6e20746865208c6c65206e616d652e>120 508.8 Q F1<2d6f>100 532.8 Q F0 <3c8c6c65206e616d653e2028>2.5 E F2<6f7574707574208c6c65206e616d65>A F0 <29>A<5370656369667920746865206f7574707574208c6c65206e616d652e>120 544.8 Q F1<2d64>100 568.8 Q F0<3c6465>2.5 E<766963653e2028>-.25 E F2 <736574206b>A .6 -.3<6579205c>-.1 H<5f5f6465>.3 E<766963655f5f>-.15 E F0 <29>A<53657420746865206b>120 580.8 Q -.15<6579>-.1 G F1<5c5f5f6465>2.65 E<766963655f5f>-.15 E F0<746f>2.5 E F3<3c6465766963653e>2.5 E F0<2e>A F1 <2d78>100 604.8 Q F0<28>2.5 E F2<656e74657220696e746572>A <616374697665206d6f6465206f6e20657272>-.15 E<6f72>-.45 E F0<29>A 1.637< 5468652061667465726c696665206f7074696f6e2e204966207a6f656d20656e636f756e 7465727320616e206572726f7220647572696e67207265>120 616.8 R 1.637 <67756c61722070726f63657373696e672c2069742077696c6c20656d6974>-.15 F 1< 6572726f72206d6573736167657320617320757375616c2c20616e64207468656e20656e 74657220696e74657261637469>120 628.8 R 1.299 -.15<7665206d>-.25 H .999 <6f64652e205468697320616c6c6f>.15 F .999<777320796f7520652e672e>-.25 F .999<746f20696e7370656374>5.999 F<7468652076>120 640.8 Q <616c756573206f66206b>-.25 E -.15<6579>-.1 G 2.5<7375>.15 G<736564206f72 2064658c6e65642077697468696e207468652070726f626c656d6174696320617265612e> -2.5 E F1<2d73>100 664.8 Q F0<3c6b>2.5 E -.15<6579>-.1 G<3e5b3d3c76>.15 E<616c3e5d2028>-.25 E F2<736574206b>A .6 -.3<65792074>-.1 H 2.5<6f76>.3 G<616c>-2.5 E F0<29>A .538<53657420746865206b>120 676.8 R -.15<6579>-.1 G F1<5c6b>3.189 E<6579>-.1 E F0<746f>3.039 E F1 -.1<7661>3.039 G<6c>.1 E F0 .539<69662070726573656e742c>3.039 F F1<31>3.039 E F0 3.039 <6f74686572776973652e20416e>3.039 F 3.039<7974>-.15 G .539 <797065206f66206b>-3.039 F .839 -.15<65792063>-.1 H .539 <616e206265207365742c20696e636c7564696e67206b>.15 F -.15<6579>-.1 G<73> .15 E .253<74616b696e67206172>120 688.8 R .253 <67756d656e747320616e64206b>-.18 F -.15<6579>-.1 G 2.753<7373>.15 G .252 <7572726f756e64656420696e2071756f7465732e204265>-2.753 F -.1<7761>-.25 G .252<7265206f6620746865207368656c6c27>.1 F 2.752<7371>-.55 G .252 <756f746520616e64206261636b736c617368>-2.752 F 3.67 <696e746572706f6c6174696f6e2e2043757272656e746c79>120 700.8 R F1 -.1 <7661>3.67 G<6c>.1 E F0 1.17<6973206e6f742065>3.67 F -.25<7661>-.25 G 1.17<6c75617465642c20736f20617070656e64696e67206f722070726570656e64696e 6720746f2061206b>.25 F 1.47 -.15<65792069>-.1 H 3.67<736e>.15 G<6f74> -3.67 E<706f737369626c652e>120 712.8 Q<7a6f656d2031312d313636>20 768 Q <3135204a756e2032303131>157.065 E<32>204.555 E 0 Cg EP %%Page: 3 3 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 153.455<7a6f656d2831292055534552>20 48 R 155.955 <434f4d4d414e4453207a6f656d283129>2.5 F/F1 10/Times-Bold@0 SF<2d65>100 84 Q F0<3c616e>2.5 E<793e2028>-.15 E/F2 10/Times-Italic@0 SF -.15<6576>C <616c7561746520616e79>.15 E 2.5<2c65>-.55 G<786974>-2.7 E F0<29>A <5468697320636175736573207a6f656d20746f2065>120 96 Q -.25<7661>-.25 G <6c75617465>.25 E/F3 10/Courier@0 SF<3c616e793e>2.5 E F0 2.5<2c77>C <7269746520616e>-2.5 E 2.5<7972>-.15 G<6573756c74207465>-2.5 E <787420746f207374646f75742c20616e642065>-.15 E<7869742e>-.15 E F1<2d45> 100 120 Q F0<3c616e>2.5 E<793e2028>-.15 E F2 -.15<6576>C <616c7561746520616e79>.15 E 2.5<2c70>-.55 G -.45<726f>-2.5 G<63656564> .45 E F0<29>A .461<5468697320636175736573207a6f656d20746f2065>120 132 R -.25<7661>-.25 G<6c75617465>.25 E F3<3c616e793e>2.961 E F0 2.961<2c77>C .461<7269746520616e>-2.961 F 2.961<7972>-.15 G .461<6573756c74207465> -2.961 F .46 <787420746f207374646f75742c20616e642070726f6365656420652e672e2077697468> -.15 F<74686520656e747279208c6c65206f7220616e20696e74657261637469>120 144 Q .3 -.15<76652073>-.25 H<657373696f6e2e>.15 E F1 <2d6368756e6b2d73697a65>100 168 Q F0<3c6e756d3e2028>2.5 E F2<7072>A <6f636573732063>-.45 E<68756e6b73206f662073697a65206e756d>-.15 E F0<29>A .608<5a6f656d2072656164732069747320696e70757420696e206368756e6b732e2049 742066756c6c792070726f6365737365732061206368756e6b206265666f7265206d6f> 120 180 R .608<76696e67206f6e207769746820746865206e65>-.15 F<7874>-.15 E .259<6f6e652e2054686973206f7074696f6e2064658c6e65732074686520286d696e69 6d756d292073697a65206f6620746865206368756e6b732e205468652073697a65206f72 20636f756e74206f6620746865206368756e6b73>120 192 R .177 <646f6573206e6f7420617420616c6c206166>120 204 R .178 <66656374207a6f656d27>-.25 F 2.678<736f>-.55 G .178 <75747075742e2054686520646566>-2.678 F .178<61756c74206d696e696d756d2063 68756e6b2073697a6520657175616c73206f6e65206d65>-.1 F -.05<6761>-.15 G <627974652e>.05 E 1.047<5a6f656d2077696c6c2072656164208c6c657320696e2074 6865697220656e746972657479206265666f726520667572746865722070726f63657373 73696e67206966>120 228 R F1<2d6368756e6b2d73697a652030>3.547 E F0 1.046 <69732073706563692d>3.547 F<8c65642e>120 240 Q .163<5a6f656d20646f657320 6e6f74206368756e6b20696e707574208c6c6573206172626974726172696c792e204974 2077696c6c20617070656e6420746f2061206368756e6b20756e74696c20697420697320 696e20746865206f75746572>120 264 R<2d>-.2 E 1.039 <6d6f73742073636f706520286e6f7420636f6e7461696e65642077697468696e20616e> 120 276 R 3.539<7962>-.15 G 1.039<6c6f636b2920616e6420746865206368756e6b 2077696c6c20656e6420776974682061206c696e6520746861742077>-3.539 F<6173> -.1 E<66756c6c7920726561642e>120 288 Q<436f6e73657175656e746c79>120 312 Q 3.724<2c69>-.65 G 3.724<6665>-3.724 G 1.225<2e672e2061208c6c6520636f6e 7461696e73206120626c6f636b202864656c696d697465642062792062616c616e636564 206375726c69657329207370616e6e696e6720746865>-3.724 F<656e74697265208c6c 65207468656e207a6f656d20697320666f7263656420746f207265616420697420696e20 69747320656e7469726574792e>120 324 Q F1<2d2d7472616365>100 348 Q F0<28> 2.5 E F2<7472>A<616365206d6f6465>-.15 E 2.5<2c64>-.1 G<656661756c74>-2.5 E F0<29>A -.35<5472>120 360 S<61636520696e20646566>.35 E <61756c74206d6f64652e>-.1 E F1<2d2d74726163652d616c6c2d6c6f6e67>100 384 Q F0<28>2.5 E F2<6c6f6e67207472>A<616365206d6f6465>-.15 E F0<29>A .098 <53657473206f6e>120 396 R F2<6d6f7374>2.598 E F0 .098 <7472616365206f7074696f6e7320696e206c6f6e67206d6f64652e>2.598 F -.35 <5472>5.098 G .097<616365206f7074696f6e73>.35 F F3<787878>2.597 E F0 .097<6e6f7420736574206861>2.597 F .397 -.15<76652074>-.2 H .097 <68656972206f>.15 F<776e>-.25 E F1<2d2d74726163652d>2.597 E<787878>120 408 Q F0<656e74727920287365652062656c6f>2.5 E<77292e>-.25 E F1 <2d2d74726163652d616c6c2d73686f7274>100 432 Q F0<28>2.5 E F2 <73686f7274207472>A<616365206d6f6465>-.15 E F0<29>A 2.232 <53657473206f6e>120 444 R F2<6d6f7374>4.732 E F0 2.232 <7472616365206f7074696f6e7320696e2073686f7274206d6f64652e>4.732 F -.35 <5472>7.232 G 2.232<616365206f7074696f6e73>.35 F F3<787878>4.732 E F0 2.232<6e6f7420736574206861>4.732 F 2.532 -.15<76652074>-.2 H 2.232 <68656972206f>.15 F<776e>-.25 E F1<2d2d74726163652d787878>120 456 Q F0 <656e74727920287365652062656c6f>2.5 E<77292e>-.25 E F1 <2d2d74726163652d6b>100 480 Q<657973>-.1 E F0<28>2.5 E F2<7472>A <616365206b>-.15 E -.3<6579>-.1 G<73>.3 E F0<29>A -.35<5472>120 492 S <616365206b>.35 E -.15<6579>-.1 G<732e>.15 E F1<2d2d74726163652d72>100 516 Q<65676578>-.18 E F0<28>2.5 E F2<7472>A<6163652072>-.15 E -1.8 -.4 <65672065>-.37 H<786573>.2 E F0<29>A -.35<5472>120 528 S<616365207265> .35 E<6765>-.15 E -.15<7865>-.15 G 2.5<7328>.15 G<692e652e20746865>-2.5 E F1<5c696e73706563742334>2.5 E F0<7072696d697469>2.5 E -.15<7665>-.25 G <292e>.15 E F1<2d7472616365>100 552 Q F0 2.5<6b28>2.5 G F2<7472>-2.5 E <616365206d6f6465>-.15 E 2.5<2c65>-.1 G<78706c69636974>-2.7 E F0<29>A<53 6574207472616365206f7074696f6e7320627920616464696e6720746865697220726570 726573656e74696e6720626974732e>120 564 Q F1<2d2d737472>100 588 Q <6573732d7772697465>-.18 E F0<28>2.5 E F2<737472>A <6573732074657374207573696e67207772697465>-.37 E F0<29>A .924 <54686973206d616b>120 600 R<6573>-.1 E F1<5c77726974652333>3.424 E F0 <7265636f>3.424 E -.15<7665>-.15 G 3.424<7266>.15 G .924 <726f6d206572726f72732e>-3.424 F .923<49742069732061207370656369616c2070 7572706f7365206f7074696f6e207573656420666f72206372656174696e67>5.924 F .142<7a6f656d207374726573732074657374207375697465732c2073756368206173> 120 612 R F3<7374726573732e617a6d>2.642 E F0 .143 <696e20746865207a6f656d2064697374726962>2.643 F<7574696f6e>-.2 E F3 <2f6578616d706c6573>2.643 E F0<73756264692d>2.643 E<726563746f72792e>120 624 Q F1<2d2d756e73616665>100 648 Q F0<28>2.5 E F2<7072>A <6f6d707420666f72205c73797374656d2333>-.45 E F0<29>A F1 <2d2d756e736166652d73696c656e74>100 660 Q F0<28>2.5 E F2 <73696d706c7920616c6c6f77205c73797374656d2333>A F0<29>A F1<2d616c6c6f> 100 672 Q<77>-.1 E F0<636d64315b3a636d64785d2b2028>2.5 E F2 <616c6c6f7761626c6520636f6d6d616e6473>A F0<29>A -.4<5769>120 684 S<7468> .4 E F1<2d2d756e73616665>3.438 E F0 .937 <73797374656d2063616c6c732061726520616c6c6f>3.438 F .937<7765642062>-.25 F .937 <75742074686520757365722069732070726f6d7074656420666f72206561636820696e> -.2 F -.2<766f>-.4 G .937<636174696f6e2e20546865>.2 F .117 <636f6d6d616e6420616e6420697473206172>120 696 R .117 <67756d656e74732028696620616e>-.18 F .117<7929206172652073686f>-.15 F .117<776e2c2062>-.25 F .118 <75742074686520535444494e20696e666f726d6174696f6e2028696620616e>-.2 F .118<792920697320776974682d>-.15 F 2.5<68656c642e2057>120 708 R<697468> -.4 E F1<2d2d756e736166652d73696c656e74>2.5 E F0 <73797374656d2063616c6c732061726520616c6c6f>2.5 E <77656420616e64207468652075736572206973206e65>-.25 E -.15<7665>-.25 G 2.5<7270>.15 G<726f6d707465642e>-2.5 E<7a6f656d2031312d313636>20 768 Q <3135204a756e2032303131>157.065 E<33>204.555 E 0 Cg EP %%Page: 4 4 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 153.455<7a6f656d2831292055534552>20 48 R 155.955 <434f4d4d414e4453207a6f656d283129>2.5 F<557365>120 84 Q/F1 10 /Times-Bold@0 SF<2d616c6c6f>3.048 E<77>-.1 E/F2 10/Times-Italic@0 SF <737472>2.5 E F0<6f72>3.048 E F1<2d2d616c6c6f>3.048 E<77>-.1 E F0<3d>A F2<737472>A F0 .548<746f20737065636966792061206c697374206f6620616c6c6f> 3.048 F -.1<7761>-.25 G .548 <626c6520636f6d6d616e64732c206173206120737472696e6720696e207768696368>.1 F<74686520636f6d6d616e6473206172652073657061726174656420627920636f6c6f6e 732e>120 96 Q F1<2d2d73797374656d2d686f6e6f72>100 120 Q F0<28>2.5 E F2 -.37<7265>C<71756972>.37 E 2.5<655c>-.37 G <73797374656d233320746f2073756363656564>-2.5 E F0<29>A -.4<5769>120 132 S .049<74682074686973206f7074696f6e20616e>.4 F<79>-.15 E/F3 10/Courier@0 SF<5c73797374656d2333>2.549 E F0 -.1<6661>2.549 G .049 <696c7572652028666f72207768617465>.1 F -.15<7665>-.25 G 2.549<7272>.15 G .049<6561736f6e2c20696e636c7564696e6720736166652062656861>-2.549 F .05 <76696f757229206973>-.2 F<7265>120 144 Q -.05<6761>-.15 G 1.031 <726465642061732061207a6f656d2066>.05 F 3.531<61696c7572652e204279>-.1 F <646566>3.531 E 1.031<61756c742c2066>-.1 F 1.03<61696c696e67207379737465 6d2063616c6c73206172652069676e6f72656420756e6465722065697468657220736166 65>-.1 F<6d6f64652c20756e73616665206d6f646520282d2d756e73616665292c206f 722073696c656e7420756e73616665206d6f646520282d2d756e736166652d73696c656e 74292e>120 156 Q F1<2d2d73706c6974>100 180 Q F0<28>2.5 E F2 <617373756d652073706c6974206f7574707574>A F0<29>A 1.622 <5468697320617373756d6573207a6f656d20696e707574207468617420616c6c6f>120 192 R 1.622 <7773206f757470757420746f206d756c7469706c65208c6c65732028652e672e>-.25 F 1.623<6368617074657273292e204974207365747320746865>6.622 F<646566>120 204 Q .658<61756c74206f75747075742073747265616d20746f>-.1 F F3 <7374646f7574>3.158 E F0 .658<28616e74696369706174696e6720637573746f6d20 6f7574707574207265646972656374696f6e2077697468>3.158 F F1 <5c7772697465746f2331>3.158 E F0<29>A <616e642073657473207468652073657373696f6e206d6163726f>120 216 Q F1 <5c5f5f73706c69745f5f>2.5 E F0<746f>2.5 E F3<31>2.5 E F0<2e>A F1 <2d2d7374617473>100 240 Q F0<28>2.5 E F2 <73686f772073796d626f6c207461626c652073746174732061667465722072756e>A F0 <29>A<53686f>120 252 Q 2.5<7773>-.25 G<796d626f6c207461626c652063686163 7465726973746963732e2053796d626f6c207461626c657320617265206d61696e746169 6e6564206173206861736865732e>-2.5 E F1<2d746c>100 276 Q F0 2.5<6b28>2.5 G F2<73657420746162206c656e677468>-2.5 E F0<29>A .376<536574207468652074 6162206c656e6774682e2048544d4c206f75747075742063616e20626520696e64656e74 6564206163636f7264696e6720746f206e657374696e67207374727563747572652c2075 73696e672074616273>120 288 R 1.036<7768696368206172652065>120 300 R 1.036<7870616e64656420746f2073696d706c65207370616365732e20427920646566> -.15 F 1.035<61756c742c2074686520746162206c656e677468206973207a65726f2c 206d65616e696e672074686174206e6f>-.1 F<696e64656e742069732073686f>120 312 Q 2.5<776e2e20546865>-.25 F<6d6178696d756d2076>2.5 E<616c7565207468 6520746162206c656e6774682063616e2062652073657420746f20697320666f75722e> -.25 E F1<2d6e7365676d656e74>100 336 Q F0 2.5<6b28>2.5 G F2<6c65>-2.5 E <76656c206f66206d616372>-.15 E 2.5<6f6e>-.45 G <657374696e6720616c6c6f776564>-2.5 E F0<29>A F1<2d6e737461636b>100 348 Q F0 2.5<6b28>2.5 G F2<73746163>-2.5 E 2.5<6b63>-.2 G<6f756e74>-2.5 E F0 <29>A F1<2d6e75736572>100 360 Q F0 2.5<6b28>2.5 G F2 <757365722064696374696f6e6172792073746163>-2.5 E 2.5<6b73>-.2 G<697a65> -2.5 E F0<29>A F1<2d6e656e>100 372 Q<76>-.4 E F0 2.5<6b28>2.5 G F2<656e> -2.5 E<766972>-.4 E<6f6e6d656e742064696374696f6e6172792073746163>-.45 E 2.5<6b73>-.2 G<697a65>-2.5 E F0<29>A F1<2d62>100 384 Q<75736572>-.2 E F0 2.5<6b28>2.5 G F2<696e697469616c20757365722064696374206361706163697479> -2.5 E F0<29>A F1<2d627a6f656d>100 396 Q F0 2.5<6b28>2.5 G F2 <696e697469616c207a6f656d2064696374206361706163697479>-2.5 E F0<29>A 1.04<50726f6261626c79206e6565646564206f6e6c7920696620796f75206861>120 408 R 1.34 -.15<76652073>-.2 H 1.04<6f6d65206f62736375726520616e642065> .15 F 1.04<787472656d652075736520666f72207a6f656d2e20546865207365>-.15 F <676d656e74>-.15 E .534<6c696d6974206170706c69657320746f2073696d706c6520 6e657374696e67206f66206d6163726f732e2054686520737461636b206c696d69742061 70706c69657320746f206e657374696e67206f66206d6163726f732074686174>120 420 R -.25<657661>120 432 S .68<6c7561746520616e206172>.25 F .681 <67756d656e74206265666f7265207573652e204561636820737563682065>-.18 F -.25<7661>-.25 G .681<6c756174696f6e20637265617465732061206e65>.25 F 3.181<7773>-.25 G .681<7461636b2e205468652075736572206c696d6974>-3.181 F 1.043<6170706c69657320746f>120 444 R F1<5c707573687b757365727d>3.543 E F0 3.543<2c74>C 1.043<686520656e>-3.543 F 3.542<766c>-.4 G 1.042 <696d6974206170706c69657320746f20746865206e657374696e67206c65>-3.542 F -.15<7665>-.25 G 3.542<6c6f>.15 G 3.542<6665>-3.542 G -.4<6e76>-3.542 G 1.042<69726f6e6d656e7473202873746172746564>.4 F<77697468>120 456 Q F3 <5c626567696e2332>2.74 E F0 .241<292e2054686520757365722064696374206361 706163697479207065727461696e7320746f2074686520696e697469616c206e756d6265 72206f662062>B<75636b>-.2 E .241<65747320616c6c6f6361746564>-.1 F .353 <666f72207573657220616e6420656e>120 468 R .352<7669726f6e6d656e74206469 6374696f6e61726965732c20616e6420746865207a6f656d206469637420636170616369 7479207065727461696e7320746f207468652064696374696f6e617279>-.4 F <636f6e7461696e696e6720746865207a6f656d207072696d697469>120 480 Q -.15 <7665>-.25 G<732e>.15 E F1<2d6c>100 504 Q F0<3c7374723e2028>2.5 E F2 <6c697374206974656d73>A F0<29>A .353 <4c697374206974656d73206964656e74698c6564206279>120 516 R F3<3c7374723e> 2.853 E F0 2.853<2e49>C 2.853<7463>-2.853 G .353<616e20626520616e>-2.853 F 2.853<796f>-.15 G<66>-2.853 E F1<616c6c>2.853 E F0<2c>A F1<8c6c746572> 2.854 E F0<2e>A F1<6c6567656e64>5.354 E F0<2c>A F1 -.2<6275>2.854 G <696c74696e>.2 E F0<2c>A F1<73657373696f6e>2.854 E F0<2c>A F1 <7472616365>2.854 E F0<2c>A<6f72>120 528 Q F1<7a6f656d>2.809 E F0 2.809 <2c4d>C .309<756c7469706c65206964656e74698c6572732063616e206265206a6f69 6e656420696e206120737472696e672c20652e672e>-2.809 F F3 .308 <2d6c206c6567656e647a6f656d>2.808 F F0 .308<7072696e74732061206c65>2.808 F<672d>-.15 E<656e6420666f6c6c6f>120 540 Q <7765642062792061206c697374696e67206f66207a6f656d207072696d697469>-.25 E -.15<7665>-.25 G<732e>.15 E F1<2d68>100 564 Q F0<28>2.5 E F2 <73686f77206f7074696f6e73>A F0<29>A<53686f>120 576 Q 2.5<7773>-.25 G <686f72742073796e6f70736973206f66206f7074696f6e732e>-2.5 E/F4 10.95 /Times-Bold@0 SF<53455353494f4e204d41>20 592.8 Q<4352>-.602 E<4f53>-.329 E F1<5c5f5f7061726d6f64655f5f>100 604.8 Q F0 1.058 <54686973206d6163726f206166>120 616.8 R 1.058<6665637473207a6f656d27> -.25 F 3.558<7372>-.55 G 1.058<6561642062656861>-3.558 F 1.059 <76696f757220696e20696e74657261637469>-.2 F 1.359 -.15<7665206d>-.25 H 3.559<6f64652e204974>.15 F 1.059 <63616e20626520736574206f6e2074686520636f6d2d>3.559 F <6d616e64206c696e65207573696e6720746865>120 628.8 Q F1<2d73>2.5 E F0 2.5 <6f7074696f6e2e2042697473>2.5 F<746861742063616e206265207365743a>2.5 E F3 24<3163>120 652.8 S<686f6d70206e65776c696e6573202872656d6f7665207468 65206e65776c696e652063686172616374657229>-24 E 24<3273>120 664.8 S <6b697020656d707479206e65776c696e6573>-24 E 24<3472>120 676.8 S<65616420 706172616772617068732028616e20656d707479206c696e652074726967676572732069 6e707574207265616429>-24 E 24<386e>120 688.8 S<65776c696e65732063616e20 62652065736361706564207573696e672061206261636b736c617368>-24 E 12 <31362072656164>120 700.8 R<6c617267652070617261677261706873202861207369 6e676c6520646f74206f6e2061206c696e65>6 E <747269676765727320696e707574207265616429>150 712.8 Q F0 <7a6f656d2031312d313636>20 768 Q<3135204a756e2032303131>157.065 E<34> 204.555 E 0 Cg EP %%Page: 5 5 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 153.455<7a6f656d2831292055534552>20 48 R 155.955 <434f4d4d414e4453207a6f656d283129>2.5 F/F1 10/Times-Bold@0 SF <5c5f5f6465>100 84 Q<766963655f5f>-.15 E F0 .572 <5468652063757272656e74206f7574707574206465>120 96 R .572<766963652c2073 65742062792074686520636f6d6d616e64206c696e65206f7074696f6e>-.25 F F1 <2d64>3.072 E F0 3.072<2e54>C<6865>-3.072 E F1<6d616e>3.072 E F0<616e64> 3.072 E F1<666171>3.072 E F0<7061636b61676573>3.072 E<737570706f7274>120 108 Q F1<68746d6c>2.5 E F0<616e64>2.5 E F1 -.18<726f>2.5 G<6666>.18 E F0 <6173206974732076>2.5 E<616c7565732e>-.25 E F1<5c5f5f666e626173655f5f> 100 120 Q F0 .242<5468652062617365206e616d65206f662074686520696e70757420 8c6c65206e616d652e204c656164696e67207061746820636f6d706f6e656e7473206172 652073747269707065642061>120 132 R -.1<7761>-.15 G .243 <792e20496620746865>.1 F F1<2d69>2.743 E F0 .965<6f7074696f6e2069732075 7365642074686520696e707574208c6c6520697320726571756972656420746f206861> 120 144 R 1.265 -.15<76652074>-.2 H<6865>.15 E/F2 10/Courier@0 SF <2e617a6d>3.465 E F0<737566>3.465 E .965 <8c782e20496e207468617420636173652074686520737566>-.25 F .965 <8c78206973>-.25 F<616c736f20737472697070656420746f206f627461696e207468 652062617365206e616d652e>120 156 Q F1<5c5f5f666e656e7472795f5f>100 168 Q F0<546865206e616d65206f662074686520656e747279208c6c652e>120 180 Q F1 <5c5f5f666e696e5f5f>100 192 Q F0 <546865208c6c652063757272656e746c79206265696e672070726f6365737365642e> 120 204 Q F1<5c5f5f666e6f75745f5f>100 216 Q F0 <546865206e616d65206f662074686520646566>120 228 Q <61756c74206f7574707574208c6c652e>-.1 E F1<5c5f5f666e706174685f5f>100 240 Q F0<546865206c656164696e6720636f6d706f6e656e74206f662074686520696e 707574208c6c65206e616d652c20706f737369626c7920656d7074792e>120 252 Q F1 <5c5f5f666e75705f5f>100 264 Q F0<546865208c6c65207468617420696e636c7564 6564207468652063757272656e74208c6c652c206966206170706c696361626c652e>120 276 Q F1<5c5f5f666e77726974655f5f>100 288 Q F0 1.824<54686973206b>120 300 R 2.124 -.15<65792069>-.1 H 4.324<7373>.15 G 1.824<6574206279>-4.324 F F2<5c77726974652333>4.324 E F0 1.825<746f20697473208c727374206172> 4.325 F 1.825<67756d656e742e2049742063616e2062652075736564206279206d6163 726f73207468617420617265>-.18 F -.15<6578>120 312 S .456 <70616e64656420647572696e672065>.15 F -.25<7661>-.25 G .456 <6c756174696f6e206f6620746865207468697264206172>.25 F .456<67756d656e74 2e20506f737369626c6520757361676520697320746f206272616e6368206f6e20746865 206e616d65>-.18 F .787<6f6620746865>120 324 R/F3 10/Times-Italic@0 SF <7772697465>3.287 E F0 .788<6f75747075742073747265616d2e2046>3.288 F .788<6f722065>-.15 F .788<78616d706c652061208c6c652063616c6c6564>-.15 F F3<696e6465>3.288 E<782e68746d6c>-.2 E F0 .788 <6d6179206265207472656174656420646966>3.288 F<666572656e746c79>-.25 E .094<66726f6d206f74686572208c6c65732e>120 336 R .094<546865206b>5.094 F .394 -.15<65792069>-.1 H 2.594<7364>.15 G .094 <656c6574656420616674657277>-2.594 F .094 <617264732e204e657374656420696e>-.1 F -.2<766f>-.4 G .094 <636174696f6e73206f66>.2 F F2<5c77726974652333>2.594 E F0 .093 <6d617920636f72>2.593 F<2d>-.2 E <727570742074686520737461747573206f662074686973206b>120 348 Q -.15<6579> -.1 G<2e>.15 E F1<5c5f5f69615f5f>100 360 Q F0<54686520696e7075742f6f7574 70757420736570617261746f72207573656420696e20696e74657261637469>120 372 Q .3 -.15<7665206d>-.25 H<6f64652e>.15 E F1<5c5f5f6c696e655f5f>100 384 Q F0 .455<546865206c696e65206e756d62657220696e20746865208c6c65206375727265 6e746c79206265696e672070726f6365737365642e>120 396 R .456 <54686973206e756d6265722077696c6c20626520636f727265637420666f7220616e> 5.455 F<79>-.15 E<696e>120 408 Q -.2<766f>-.4 G .674<636174696f6e206f75 7473696465207468652073636f7065206f662061206d6163726f2e2046>.2 F .673 <6f7220616e>-.15 F 3.173<7969>-.15 G -1.9 -.4<6e76206f>-3.173 H .673<63 6174696f6e2077697468696e2061206d6163726f2074686520726573756c742077696c6c> .4 F<626520746865206c696e65206e756d626572206f662074686520636c6f73696e67 206375726c79206f6620746865206f757465726d6f737420636f6e7461696e696e67206d 6163726f2e2054686520666f6c6c6f>120 420 Q<77696e67>-.25 E F2 <5c5f5f6c696e655f5f>138 444 Q<5c5f5f6c696e655f5f>138 456 Q <5c5f5f6c696e655f5f>138 468 Q<5c67726f75707b>138 480 Q <5c5f5f6c696e655f5f>138 492 Q<5c67726f75707b5c5f5f6c696e655f5f7d>138 504 Q<5c5f5f6c696e655f5f7d>138 516 Q F0<526573756c747320696e>120 540 Q F2 <31>138 564 Q<32>138 576 Q<33>138 588 Q<37>138 600 Q<37>138 612 Q<37>138 624 Q F1<5c5f5f73656172>100 648 Q<6368706174685f5f>-.18 E F0 10.803 <4176>120 660 S<61726172>-11.053 E 10.803<6763>-.18 G 8.304<6f6e7461696e 696e672061206c697374206f6620706174687320746f20736561726368207768656e2061 208c6c6520697320746f206265>-10.803 F .829<696e636c756465642f696d706f7274 65642f726561642f6c6f616465642e205768656e20796f75207374617274207a6f656d2c 2074686973206b>120 672 R 1.129 -.15<65792073>-.1 H .829 <686f756c6420636f6e7461696e20746865206c6f636174696f6e>.15 F .029 <6f6620746865>120 684 R F1<6d616e2e7a6d6d>2.529 E F0<616e64>2.529 E F1 <6661712e7a6d6d>2.529 E F0 .029<7061636b616765208c6c65732e>2.529 F .029 <497420697320616476697361626c65206e6f7420746f206f>5.029 F -.15<7665>-.15 G .03<7277726974652074686973206b>.15 F .33 -.15<65792062>-.1 H .03 <757420746f>-.05 F<617070656e6420746f20697420696e73746561642e>120 696 Q F1<5c5f5f7a6f656d737461745f5f>100 708 Q F0 1.053 <53657420746f206f6e65206f66>120 720 R F2<6f6b>3.553 E F0<2c>A F2 <746f77656c>3.553 E F0 1.053 <2874686174206f6e65206973206120626974206c616d65292c206f72>3.553 F F2 <6572726f72>3.553 E F0 1.052 <6279206569746865722074686520696e746572707265746572>3.553 F 3.552<2c61> -.4 G<6e>-3.552 E<7a6f656d2031312d313636>20 768 Q <3135204a756e2032303131>157.065 E<35>204.555 E 0 Cg EP %%Page: 6 6 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 153.455<7a6f656d2831292055534552>20 48 R 155.955 <434f4d4d414e4453207a6f656d283129>2.5 F<6f6363757272656e6365206f66>120 84 Q/F1 10/Courier@0 SF<5c63617463682332>2.5 E F0 2.5<2c6f>C<72>-2.5 E F1<5c7472792331>2.5 E F0<2e>A/F2 10/Times-Bold@0 SF <5c5f5f7a6f656d7075745f5f>100 96 Q F0<536574206279>120 108 Q F1 <5c7472792331>2.5 E F0<746f2074686520706f737369626c79207472756e63617465 6420726573756c74206f662070726f63657373696e6720697473206172>2.5 E <67756d656e742e>-.18 E F2<5c5f5f6c635f5f>100 120 Q F0 .855<457870616e64 7320746f2061206c656674206375726c792e204974206973206861726420746f208c6e64 2061206e65656420666f72207468697320ad20746865207a6f656d207374726573732073 75697465207573657320697420746f>120 132 R<67656e657261746520612070617274 6963756c61722073796e746178206572726f7220617420612064656570657220696e7465 72707265746174696f6e206c65>120 144 Q -.15<7665>-.25 G<6c2e>.15 E F2 <5c5f5f72>100 156 Q<635f5f>-.18 E F0 <457870616e647320746f2061207269676874206375726c792e>120 168 Q/F3 10.95 /Times-Bold@0 SF<54484520534554204d4f44494649455253>20 184.8 Q F0 <546865>100 196.8 Q F1<5c7365742333>4.241 E F0<7072696d697469>4.241 E 2.041 -.15<76652061>-.25 H<6c6c6f>.15 E 1.741<77732061>-.25 F F1 <7b6d6f6465737d7b3c6d6f646966696572733e7d>4.241 E F0<64697265637469> 4.241 E 2.041 -.15<76652069>-.25 H 4.241<6e69>.15 G 1.741 <7473208c727374206172>-4.241 F<67756d656e742e>-.18 E<48657265>100 208.8 Q/F4 10/Times-Italic@0 SF<3c6d6f64698c6572>2.5 E<733e>-.1 E F0<63616e20 6265206120636f6d62696e6174696f6e206f662073696e676c652d6c6574746572206d6f 64698c6572732c2065616368206465736372696265642062656c6f>2.5 E<772e>-.25 E 15.56<6161>100 232.8 S<7070656e6420746f20746865206b>-15.56 E -.15<6579> -.1 G 2.5<2c64>-.5 G 2.5<6f6e>-2.5 G<6f74206f>-2.5 E -.15<7665>-.15 G <7277726974652c20637265617465206966206e6f742065>.15 E<78697374696e672e> -.15 E 15.56<6363>100 244.8 S<6f6e646974696f6e616c6c793b206f6e6c79207365 74206966206e6f7420616c72656164792064658c6e65642e>-15.56 E 15.56<6565>100 256.8 S<78697374696e673b207570646174652065>-15.71 E<78697374696e67206b> -.15 E -.15<6579>-.1 G 2.5<2c70>-.5 G<6f737369626c7920696e206c6f>-2.5 E <7765722064696374696f6e6172792e>-.25 E 15<6767>100 268.8 S<6c6f62616c3b 2073657420696e2074686520676c6f62616c2028626f74746f6d29207573657220646963 74696f6e6172792e>-15 E 15<7575>100 280.8 S <6e6172793b20646f206e6f7420696e746572707265742076>-15 E<61726172>-.25 E 2.5<6769>-.18 G<6e>-2.5 E F1<3c616e793e>2.5 E F0<6173206b>2.5 E -.15 <6579>-.1 G<2d76>.15 E<616c7565206c697374202864617461206b>-.25 E -.15 <6579>-.1 G 2.5<736f>.15 G<6e6c7929>-2.5 E 15<7676>100 292.8 S<61726172> -15.25 E<673b20696e746572707265742076>-.18 E<61726172>-.25 E 2.5<6769> -.18 G<6e>-2.5 E F1<3c616e793e>2.5 E F0<6173206b>2.5 E -.15<6579>-.1 G <2d76>.15 E<616c7565206c69737420287265>-.25 E<67756c6172206b>-.15 E -.15 <6579>-.1 G 2.5<736f>.15 G<6e6c79292e>-2.5 E 12.78<7777>100 304.8 S <61726e206966206b>-12.88 E .3 -.15<6579206578>-.1 H<6973747320286c696b> .15 E<65>-.1 E F1<5c6465662332>2.5 E F0<616e64>2.5 E F1<5c646566782332> 2.5 E F0<292e>A 15<7865>100 316.8 S<7870616e64206172>-15.15 E <67756d656e7420286c696b>-.18 E<65>-.1 E F1<5c736574782332>2.5 E F0 <616e64>2.5 E F1<5c646566782332>2.5 E F0<292e>A F3 <54484520494e5350454354205355424c414e4755>20 333.6 Q -.602<4147>-.657 G <45>.602 E F0<546865>100 345.6 Q F1<5c696e73706563742334>4.324 E F0 <7072696d697469>4.324 E 2.124 -.15<76652074>-.25 H<616b>.15 E 1.824 <657320666f7572206172>-.1 F 1.824<67756d656e74732e20546865206c616e677561 67657320616363657074656420627920746865208c727374207477>-.18 F<6f>-.1 E <6172>100 357.6 Q 1.567 <67756d656e747320617265206465736372696265642062656c6f>-.18 F 1.567 <772e20546865207468697264206172>-.25 F 1.567<67756d656e7420697320612072 65706c6163656d656e7420737472696e67206f722061207265706c6163656d656e74> -.18 F .263<6d6163726f20616363657074696e67206261636b2d7265666572656e6365 732028737570706c69656420617320616e20616e6f6e>100 369.6 R .263 <796d6f7573206d6163726f292e2054686520666f75727468206172>-.15 F .264 <67756d656e7420697320746865>-.18 F <6461746120746f2062652070726f6365737365642e>100 381.6 Q F2<6172>100 405.6 Q 2.5<6731>-.1 G F0 .302<497320612076>100 417.6 R<61726172>-.25 E .302 <672e2043757272656e746c79206974206163636570747320612073696e676c65206b> -.18 F -.15<6579>-.1 G F4<6d6f6473>2.952 E F0 .302 <666f72207768696368207468652076>2.802 F .301 <616c75652073686f756c64206265206120636f6d6d612d736570612d>-.25 F .81 <7261746564206c697374206f>100 429.6 R -.15<7665>-.15 G 3.311<7274>.15 G .811<68652077>-3.311 F<6f726473>-.1 E F4<706f736978>3.311 E F0<2c>A F4 <6963617365>3.311 E F0<2c>A F4<646f74616c6c>3.311 E F0<2c>A F4<69746572> 3.311 E .811<2d6c696e65732069746572>-.2 F<2d6172>-.2 E<6773>-.37 E F0 <2c>A F4<6d617463>3.311 E<682d6f6e6365>-.15 E F0<2c>A F4<646973636172> 3.311 E<642d6e6d70>-.37 E F0<2c>A F4<6469732d>3.311 E<636172>100 441.6 Q <642d6e696c2d6f7574>-.37 E F0<2c>A F4<646973636172>2.5 E<642d6d697373> -.37 E F0<2c>A F4<636f756e742d6d617463>2.5 E<686573>-.15 E F0 5<2e41>C <6c7465726e617469>-5 E -.15<7665>-.25 G <6c7920726570656174656420757365206f66>.15 E F4<6d6f6473>2.5 E F0 <697320616c6c6f>2.5 E<7765642e>-.25 E F2<6172>100 465.6 Q 2.5<6732>-.1 G F0 .816<49732061207265>100 477.6 R .816<67756c61722065>-.15 F .816 <787072657373696f6e2e2054>-.15 F .815 <696c6465207061747465726e73206172652065>-.35 F .815<7870616e646564206163 636f7264696e6720746f20616c6c206f6620746865205a4f454d2c20554e49582c20616e 64>-.15 F<524547455820736368656d65732e>100 489.6 Q<526566657220746f>5 E F2<54494c444520455850>2.5 E<414e53494f4e>-.74 E F0<666f722074686573652e> 2.5 E<546865207468697264206172>100 513.6 Q<67756d656e74206973206120636f 6e7374616e7420737472696e67206f7220616e20616e6f6e>-.18 E<796d6f7573206b> -.15 E -.15<6579>-.1 G 2.5<2c74>-.5 G<686520666f75727468206172>-2.5 E <67756d656e7420697320646174612e>-.18 E F3 <544845205452205355424c414e4755>20 530.4 Q -.602<4147>-.657 G<45>.602 E F0<546865>100 542.4 Q F1<5c74722332>4.033 E F0<7072696d697469>4.033 E 1.833 -.15<76652074>-.25 H<616b>.15 E 1.533<6573207477>-.1 F 4.033<6f61> -.1 G -.18<7267>-4.033 G 1.533<756d656e74732e20546865208c727374206172> .18 F 1.534<67756d656e7420636f6e7461696e73206b>-.18 F -.15<6579>-.1 G <2d76>.15 E 1.534<616c75652070616972732e20546865>-.25 F .996 <6163636570746564206b>100 554.4 R -.15<6579>-.1 G 3.496<7361>.15 G<7265> -3.496 E F4<6672>3.496 E<6f6d>-.45 E F0<616e64>3.496 E F4<746f>3.496 E F0 .996<7768696368206d75737420616c>3.496 F -.1<7761>-.1 G .996 <7973206f6363757220746f676574686572>.1 F 3.496<2c61>-.4 G<6e64>-3.496 E F4<64656c657465>3.496 E F0<616e64>3.496 E F4<737175617368>3.496 E F0 5.996<2e54>C<6865>-5.996 E -.25<7661>100 566.4 S .439 <6c756573206f66207468657365206b>.25 F -.15<6579>-.1 G 2.939<736d>.15 G .439<7573742062652076>-2.939 F<616c6964>-.25 E F4<7472>2.939 E <616e736c6174696f6e>-.15 E F0 2.939 <73706563698c636174696f6e732e2054686973>2.939 F<7072696d697469>2.939 E .74 -.15<76652074>-.25 H .44<72616e73666f726d73207468652064617461>.15 F 1.991<696e20746865207365636f6e64206172>100 578.4 R 1.991 <67756d656e74206279207375636365737369>-.18 F -.15<7665>-.25 G 1.991<6c79 206170706c79696e67207472616e736c6174696f6e2c2064656c6574696f6e20616e6420 737175617368696e6720696e2074686174>.15 F<6f726465722e204f6e6c7920746865 207472616e73666f726d6174696f6e73207468617420617265206e6565646564206e6565 642062652073706563698c65642e>100 590.4 Q -.35<5472>100 614.4 S<616e736c 6174696f6e2073706563698c636174696f6e7320617265207375626a656374656420746f 20554e49582074696c64652065>.35 E <7870616e73696f6e206173206465736372696265642062656c6f>-.15 E<772e>-.25 E 2.197<5468652073796e746178206163636570746564206279207472616e736c6174696f 6e2073706563698c636174696f6e7320697320616c6d6f73742066756c6c7920636f6d70 6c69616e742077697468207468652073796e746178>100 638.4 R .823 <6163636570746564206279>100 650.4 R F2<7472>3.323 E F0 .823 <2831292c20776974682074687265652065>B .822<7863657074696f6e732e20466972 73742c20726570656174732061726520696e74726f6475636564206173>-.15 F F1 <5b2a612a32305d>3.322 E F0 .822<726174686572207468616e>3.322 F F1 <5b612a32305d>100 662.4 Q F0 2.798<2e53>C .299 <65636f6e642c2072616e6765732063616e2028666f72206e6f>-2.798 F .299 <7729206f6e6c7920626520656e7465726564206173>-.25 F F1<582d59>2.799 E F0 2.799<2c6e>C .299<6f74206173>-2.799 F F1<5b582d595d>2.799 E F0<2e>A F1 <58>5.299 E F0<616e64>2.799 E F1<59>2.799 E F4<63616e>2.799 E F0<6265> 2.799 E .23<656e746572656420696e20656974686572206f6374616c206f72206865> 100 674.4 R .23<7861646563696d616c206e6f746174696f6e20287365652066757274 6865722062656c6f>-.15 F 2.73<77292e204173>-.25 F .23 <616e206164646974696f6e616c20666561747572652c20746865>2.73 F .14 <6d6167696320726570656174206f70657261746f72>100 686.4 R F1<5b2a61235d> 2.641 E F0 .141<73746f7073206f6e20626f746820636c61737320616e642072616e67 6520626f756e6461726965732e204368617261637465722073706563698c636174696f6e 73>2.641 F<63616e20626520636f6d706c656d656e7465642062792070726563656469 6e67207468656d207769746820746865206361726574>100 698.4 Q F1<5e>2.5 E F0 <2e>A .695<53706563698c636174696f6e73206d617920636f6e7461696e2072616e67 6573206f6620636861726163746572732073756368206173>100 722.4 R F1<612d7a> 3.195 E F0<616e64>3.194 E F1<302d39>3.194 E F0 5.694<2e50>C .694 <6f7369782063686172616374657220636c6173736573>-5.694 F <7a6f656d2031312d313636>20 768 Q<3135204a756e2032303131>157.065 E<36> 204.555 E 0 Cg EP %%Page: 7 7 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 153.455<7a6f656d2831292055534552>20 48 R 155.955 <434f4d4d414e4453207a6f656d283129>2.5 F<61726520616c6c6f>100 84 Q <7765642e205468652061>-.25 E -.25<7661>-.2 G <696c61626c6520636c617373657320617265>.25 E/F1 10/Courier@0 SF <5b3a616c6e756d3a5d>118 108 Q<5b3a616c7068613a5d>118 120 Q <5b3a636e74726c3a5d>118 132 Q<5b3a64696769743a5d>118 144 Q <5b3a67726170683a5d>118 156 Q<5b3a6c6f7765723a5d>118 168 Q <5b3a7072696e743a5d>118 180 Q<5b3a70756e63743a5d>118 192 Q <5b3a73706163653a5d>118 204 Q<5b3a75707065723a5d>118 216 Q <5b3a7864696769743a5d>118 228 Q F0 .32<436861726163746572732063616e2062 652073706563698c6564207573696e67206f6374616c206e6f746174696f6e2c20652e67 2e>100 252 R F1<5c303132>5.321 E F0 .321<656e636f64657320746865206e65> 2.821 F .321<776c696e652e20557365>-.25 F F1<5c313733>2.821 E F0<666f72> 2.821 E .14<746865206f70656e696e67206375726c79>100 264 R<2c>-.65 E F1 <5c313735>2.64 E F0 .14<666f722074686520636c6f73696e67206375726c79>2.64 F<2c>-.65 E F1<5c313334>2.639 E F0 .139 <666f7220746865206261636b736c6173682c20616e64>2.639 F F1<5c303336>2.639 E F0 .139<666f7220746865206361726574206966>2.639 F .971<6974206973207468 65208c7273742063686172616374657220696e20612073706563698c636174696f6e2e> 100 276 R/F2 10/Times-Italic@0 SF<444f4e2754>3.471 E F0<757365>3.471 E F1<5c5c>3.471 E F0<2c>A F1<5c7b>3.471 E F0 3.471<2c6f>C<72>-3.471 E F1 <5c7d>2.5 E F0 .972<696e2074686973206361736521204865>3.472 F <7861646563696d616c>-.15 E<6e6f746174696f6e206973207772697474656e206173> 100 288 Q F1<5c783762>2.5 E F0 <28746865206c656674206375726c7920696e207468697320696e7374616e6365292e> 2.5 E<536565>100 312 Q/F3 10/Times-Bold@0 SF<4558414d504c4553>2.5 E F0 <666f7220616e2065>2.5 E<78616d706c65206f66>-.15 E F1<74722332>2.5 E F0 <75736167652e>2.5 E/F4 10.95/Times-Bold@0 SF<54494c444520455850>20 328.8 Q<414e53494f4e>-.81 E F0 2.725<536f6d65207072696d697469>100 340.8 R -.15 <7665>-.25 G 5.225<7369>.15 G<6e74657266>-5.225 E 2.724<6163652077697468 20554e4958206c696272617269657320746861742072657175697265206261636b736c61 7368206573636170652073657175656e63657320746f>-.1 F 1.2 <656e636f6465206365727461696e20746f6b>100 352.8 R 1.2<656e73206f72206368 61726163746572732e20546865206261636b736c617368206973207370656369616c2069 6e207a6f656d20746f6f20616e6420776974686f75742066757274686572>-.1 F 1.162 <6d656173757265732069742063616e206265636f6d652076>100 364.8 R 1.161<6572 792063756d626572736f6d6520746f20656e636f64652074686520636f72726563742065 73636170652073657175656e636573206173206974206973206e6f74>-.15 F<616c>100 376.8 Q -.1<7761>-.1 G .5<797320636c65617220776869636820746f6b>.1 F .501 <656e732073686f756c642062652065736361706564206f7220756e70726f7465637465 64206174207768617420706f696e742e20497420697320657370656369616c6c79206469 66>-.1 F<8c2d>-.25 E<63756c7420746f2068616e646c6520746865207a6f656d2063 6861726163746572732077697468207370656369616c206d65616e696e672c>100 388.8 Q F1<7b>2.5 E F0<2c>A F1<7d>2.5 E F0<616e64>2.5 E F1<5c>2.5 E F0<2e>A .182<546865207477>100 412.8 R 2.682<6f70>-.1 G<72696d697469>-2.682 E -.15<7665>-.25 G 2.682<7375>.15 G .182 <6e64657220636f6e73696465726174696f6e20617265>-2.682 F F3 <5c696e73706563742334>2.681 E F0<616e64>2.681 E F3<5c74722332>2.681 E F0 5.181<2e42>C .181 <6f7468207472656174207468652074696c646520617320616e20616464692d>-5.181 F .908<74696f6e616c206573636170652063686172616374657220666f72206365727461 696e206172>100 424.8 R .909<67756d656e74732028617320646f63756d656e746564 20696e207468652075736572206d616e75616c292e205468657365206172>-.18 F <67752d>-.18 E .958 <6d656e747320617265207375626a656374656420746f2074696c64652065>100 436.8 R .957<7870616e73696f6e2c207768657265207468652074696c646520616e64207468 65206368617261637465722069742070726f636565647320617265207472616e732d> -.15 F 1.188<6c6174656420746f2061206e65>100 448.8 R 3.688<7763>-.25 G 1.188<6861726163746572206f72206368617261637465722073657175656e63652e2054 686572652061726520746872656520646966>-3.688 F 1.188 <666572656e742073657473206f662074696c646520657363617065732c>-.25 F .906 <5a4f454d2c20554e495820616e6420524547455820657363617065732e>100 460.8 R F3<5c74722332>3.406 E F0 .906 <6f6e6c79206163636570747320554e495820657363617065732c>3.406 F F3 <5c696e73706563742334>3.406 E F0 .905<6163636570747320616c6c2e>3.405 F -.35<5469>100 472.8 S 2.263<6c64652065>.35 F 2.263 <7870616e73696f6e20697320616c>-.15 F -.1<7761>-.1 G 2.264<79732074686520 6c6173742070726f63657373696e672073746570206265666f726520737472696e677320 61726520706173736564206f6e20746f2065>.1 F<787465726e616c>-.15 E <6c69627261726965732e>100 484.8 Q .971 <546865205a4f454d20736368656d6520636f6e7461696e7320736f6d6520636f6e>100 508.8 R -.15<7665>-.4 G .971 <6e69656e636520657363617065732c2073756368206173>.15 F F1<7e45>3.471 E F0 .97<746f20656e636f6465206120646f75626c65206261636b2d>3.471 F <736c6173682e>100 520.8 Q F3<5a4f454d2074696c646520657870616e73696f6e> 100 544.8 Q<6d6574612073657175656e6365>102.5 568.8 Q -.18<7265>7.5 G <706c6163656d656e74>.18 E <2e2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2e>100 580.8 Q 12.5<7c7e>100 592.8 S 17.5<7e7c>-12.5 G 17.5<7e7c>-2.5 G 12.5 <7c7e>100 604.8 S 17.5<457c>-12.5 G 12.5<5c5c207c>-2.5 F 12.5<7c7e>100 616.8 S 17.5<657c>-12.5 G 17.5<5c7c>-2.5 G 12.5<7c7e>100 628.8 S 17.5 <497c>-12.5 G 12.5<5c7b207c>-2.5 F 12.5<7c7e>100 640.8 S 17.5<4a7c>-12.5 G 12.5<5c7d207c>-2.5 F 12.5<7c7e>100 652.8 S 17.5<787c>-12.5 G 12.5 <5c78207c>-2.5 F 12.5<7c7e>100 664.8 S 17.5<697c>-12.5 G 17.5<7b7c>-2.5 G 12.5<7c7e>100 676.8 S 17.5<6a7c>-12.5 G 17.5<7d7c>-2.5 G <602d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d27>100 688.8 Q F0 .359<546865207a6f656d2074722073706563698c636174696f6e206c616e 67756167652061636365707473>100 712.8 R F1<5c782a2a>2.859 E F0 .359 <6173206865>2.859 F .359 <7861646563696d616c206e6f746174696f6e2c20652e672e>-.15 F F1<5c783061> 2.86 E F0 .36<64656e6f7465732061>2.86 F<6e65>100 724.8 Q <776c696e6520696e2074686520415343494920636861726163746572207365742e>-.25 E<7a6f656d2031312d313636>20 768 Q<3135204a756e2032303131>157.065 E<37> 204.555 E 0 Cg EP %%Page: 8 8 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 153.455<7a6f656d2831292055534552>20 48 R 155.955 <434f4d4d414e4453207a6f656d283129>2.5 F/F1 10/Times-Bold@0 SF <554e49582074696c646520657870616e73696f6e>100 84 Q <6d6574612073657175656e6365>102.5 108 Q -.18<7265>7.5 G <706c6163656d656e74>.18 E <2e2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2e>100 120 Q 12.5<7c7e>100 132 S 17.5<617c>-12.5 G 12.5<5c61207c>-2.5 F 12.5<7c7e> 100 144 S 17.5<627c>-12.5 G 12.5<5c62207c>-2.5 F 12.5<7c7e>100 156 S 17.5<667c>-12.5 G 12.5<5c66207c>-2.5 F 12.5<7c7e>100 168 S 17.5<6e7c> -12.5 G 12.5<5c6e207c>-2.5 F 12.5<7c7e>100 180 S 17.5<727c>-12.5 G 12.5 <5c72207c>-2.5 F 12.5<7c7e>100 192 S 17.5<747c>-12.5 G 12.5<5c74207c> -2.5 F 12.5<7c7e>100 204 S 17.5<767c>-12.5 G 12.5<5c76207c>-2.5 F 12.5 <7c7e>100 216 S 17.5<307c>-12.5 G 12.5<5c30207c>-2.5 F 12.5<7c7e>100 228 S 17.5<317c>-12.5 G 12.5<5c31207c>-2.5 F 12.5<7c7e>100 240 S 17.5<327c> -12.5 G 12.5<5c32207c>-2.5 F 12.5<7c7e>100 252 S 17.5<337c>-12.5 G 12.5 <5c33207c>-2.5 F <602d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d27>100 264 Q<52454745582074696c646520657870616e73696f6e>100 288 Q <6d6574612073657175656e6365>102.5 312 Q -.18<7265>7.5 G <706c6163656d656e74>.18 E <2e2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2e>100 324 Q 12.5<7c7e>100 336 S 17.5<5e7c>-12.5 G 12.5<5c5e207c>-2.5 F 12.5<7c7e> 100 348 S 17.5<2e7c>-12.5 G 12.5<5c2e207c>-2.5 F 12.5<7c7e>100 360 S 17.5<5b7c>-12.5 G 12.5<5c5b207c>-2.5 F 12.5<7c7e>100 372 S 17.5<247c> -12.5 G 12.5<5c24207c>-2.5 F 12.5<7c7e>100 384 S 17.5<287c>-12.5 G 12.5 <5c28207c>-2.5 F 12.5<7c7e>100 396 S 17.5<297c>-12.5 G 12.5<5c29207c> -2.5 F 12.5<7c7e>100 408 S 17.5<7c7c>-12.5 G 12.5<5c7c207c>-2.5 F 12.5 <7c7e>100 420 S 17.5<2a7c>-12.5 G 12.5<5c2a207c>-2.5 F 12.5<7c7e>100 432 S 17.5<2b7c>-12.5 G 12.5<5c2b207c>-2.5 F 12.5<7c7e>100 444 S 17.5<3f7c> -12.5 G 12.5<5c3f207c>-2.5 F <602d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d27>100 456 Q/F2 10.95/Times-Bold@0 SF<454e564952>20 484.8 Q<4f4e4d454e54>-.329 E F0 .908<54686520656e>100 496.8 R .908<7669726f6e6d656e742076>-.4 F .908 <61726961626c65205a4f454d53454152434850>-.25 F -1.11<4154>-.92 G 3.408 <486d>1.11 G .908<617920636f6e7461696e206120636f6c6f6e20616e642f6f722077 68697465737061636520736570612d>-3.408 F 1.526<7261746564206c697374206f66 2070617468732e2049742077696c6c2062652075736564207768656e2073656172636869 6e6720666f72208c6c657320696e636c7564656420766961206f6e65206f6620746865> 100 508.8 R/F3 10/Courier@0 SF<646f66696c65>4.026 E F0<616c6961736573> 100 520.8 Q F3<5c696e707574>3.918 E F0<2c>A F3<5c696d706f7274>3.918 E F0 <2c>A F3<5c72656164>3.918 E F0 3.917<2c61>C<6e64>-3.917 E F3<5c6c6f6164> 3.917 E F0 6.417<2e4e>C 1.417 <6f7465207468617420746865207a6f656d206d6163726f>-6.417 F F3 <5c5f5f7365617263682d>3.917 E<706174685f5f>100 532.8 Q F0 .045<636f6e74 61696e7320746865206c6f636174696f6e20776865726520746865207a6f656d206d6163 726f208c6c6573207765726520636f70696564206174207468652074696d65206f662069 6e7374616c6c6174696f6e>2.544 F<6f66207a6f656d2e>100 544.8 Q F2<444941>20 561.6 Q<474e4f5354494353>-.602 E F0 .402<4f6e206572726f72>100 573.6 R 2.902<2c5a>-.4 G .402<6f656d207072696e74732061208c6c65206e616d6520616e64 2061206c696e65206e756d62657220746f2077686963682069742077>-2.902 F .401 <61732061626c6520746f20747261636520746865206572726f722e20546865>-.1 F .571<6e756d626572207265706f72746564206973207468652073616d65206173207468 65206f6e652073746f72656420696e207468652073657373696f6e206d6163726f>100 585.6 R F3<5c5f5f6c696e655f5f>3.072 E F0 3.072<2e46>C .572 <6f7220616e206572726f72>-3.222 F<2d>-.2 E .214<747269676572696e67206d61 63726f207768696368206973206e6f74206e65737465642077697468696e20616e6f7468 6572206d6163726f20746865206c696e65206e756d6265722073686f756c642062652063 6f72726563742e2046>100 597.6 R<6f72>-.15 E 2.827<616d>100 609.6 S .328< 6163726f207468617420646f6573206f63637572206e65737465642077697468696e2061 6e6f74686572206d6163726f20746865206c696e65206e756d6265722077696c6c206265 20746865206c696e65206e756d626572206f66>-2.827 F<74686520636c6f73696e6720 6375726c7920696e20746865206f757465726d6f737420636f6e7461696e696e67206d61 63726f2e>100 621.6 Q 1.387<496620696e2064657370616972>100 645.6 R 3.886 <2c75>-.4 G 1.386 <7365206f6e65206f66207468652074726163696e67206d6f6465732c>-3.886 F F1 <2d2d74726163652d6b>3.886 E<657973>-.1 E F0 1.386 <6973206f6e65206f6620746865208c72737420746f20636f6d6520746f206d696e642e> 3.886 F<416e6f7468657220706f73736962696c69747920697320746f20737570706c79 20746865>100 657.6 Q F1<2d78>2.5 E F0<6f7074696f6e2e>2.5 E F2 -.11<4255> 20 674.4 S<4753>.11 E F0 .321<4e6f206b6e6f>100 686.4 R .321<776e2062> -.25 F<7567732e>-.2 E F1<5c696e73706563742334>2.821 E F0 .321 <686173206e6f74207265636569>2.821 F -.15<7665>-.25 G 2.822<6474>.15 G .322<686f726f756768207374726573732d74657374696e672c20616e6420746865206d 6f72652065736f7465726963207061727473>-2.822 F <6f662069747320696e74657266>100 698.4 Q <6163652077696c6c2070726f6261626c79206368616e67652e>-.1 E <7a6f656d2031312d313636>20 768 Q<3135204a756e2032303131>157.065 E<38> 204.555 E 0 Cg EP %%Page: 9 9 %%BeginPageSetup BP %%EndPageSetup /F0 10/Times-Roman@0 SF 153.455<7a6f656d2831292055534552>20 48 R 155.955 <434f4d4d414e4453207a6f656d283129>2.5 F/F1 10.95/Times-Bold@0 SF <53454520414c534f>20 84 Q/F2 10/Times-Italic@0 SF<416570686561>100 96 Q F0<6973206120646f63756d656e7420617574686f72696e67206672616d65>2.5 E -.1 <776f>-.25 G<726b206c6172>.1 E <67656c7920666f722048544d4c20646f63756d656e74732e>-.18 E F2 -.8<506f>100 120 S 1.191<727461626c6520556e697820446f63756d656e746174696f6e>.8 F F0 <70726f>3.691 E 1.191<7669646573207477>-.15 F 3.691<6f6d>-.1 G 1.191<69 6e692d6c616e67756167657320666f7220617574686f72696e6720696e2074686520756e 697820656e>-3.691 F<7669726f6e2d>-.4 E<6d656e742e205468657365206c616e67 75616765732c207075642d6d616e20616e64207075642d66>100 132 Q <61712061726520626f7468207772697474656e20696e207a6f656d2e>-.1 E F1 <4558414d504c4553>20 148.8 Q F0<5468697320697320612072656c617469>100 160.8 Q -.15<7665>-.25 G<6c79206e65>.15 E 2.5<7773>-.25 G<656374696f6e2c 2061696d656420617420617373656d626c696e672075736566756c206f722065>-2.5 E <78706c616e61746f727920736e6970706574732e>-.15 E<43726561746520612076> 100 184.8 Q<61726172>-.25 E 2.5<6763>-.18 G<6f6e7461696e696e67208c6c6520 6e616d6573206d61746368696e672061207061747465726e2028>-2.5 E/F3 10 /Courier@0 SF<706e67>A F0<696e20746869732065>2.5 E<78616d706c65292e>-.15 E F3<5c736574787b696d616765737d7b>100 208.8 Q<5c696e73706563747b>118 220.8 Q<7b6d6f64737d7b697465722d6c696e65732c646973636172642d6d6973737d> 136 232.8 Q<7d7b282e2a7e2e706e67297d7b5f23317b7b5c317d7d7d7b5c7379737465 6d7b6c737d7d>118 244.8 Q<7d>100 256.8 Q F0 <557365206d6167696320626f756e646172792073746f70732077697468>100 280.8 Q F3<74722332>2.5 E F0<2e>A F3<5c74727b>100 304.8 Q<7b66726f6d7d7b5b3a6c6f 7765723a5d5b3a75707065723a5d5b3a64696769743a5d5b3a73706163653a5d5b3a7075 6e63743a5d7d>118 316.8 Q <7b746f7d7b5b2a4c235d5b2a55235d5b2a44235d5b2a53235d5b2a50235d7d7d7b>118 328.8 Q <2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40>106 340.8 Q<4142434445464748494a4b4c4d4e4f505152535455565758595a>100 352.8 Q <5b5c5c5d5e5f60>100 364.8 Q <6162636465666768696a6b6c6d6e6f707172737475767778797a>100 376.8 Q <5c7b7c5c7d7e5d7d>100 388.8 Q F1 -.548<4155>20 417.6 S<54484f52>.548 E F0<5374696a6e2076>100 429.6 Q<616e20446f6e67656e2e>-.25 E <7a6f656d2031312d313636>20 768 Q<3135204a756e2032303131>157.065 E<39> 204.555 E 0 Cg EP %%Trailer end %%EOF zoem-11-166/doc/zoem.10000644000402500021140000006267511576103407011320 00000000000000.\" Copyright (c) 2011 Stijn van Dongen .TH "zoem" 1 "15 Jun 2011" "zoem 11-166" "USER COMMANDS " .po 2m .de ZI .\" Zoem Indent/Itemize macro I. .br 'in +\\$1 .nr xa 0 .nr xa -\\$1 .nr xb \\$1 .nr xb -\\w'\\$2' \h'|\\n(xau'\\$2\h'\\n(xbu'\\ .. .de ZJ .br .\" Zoem Indent/Itemize macro II. 'in +\\$1 'in +\\$2 .nr xa 0 .nr xa -\\$2 .nr xa -\\w'\\$3' .nr xb \\$2 \h'|\\n(xau'\\$3\h'\\n(xbu'\\ .. .if n .ll -2m .am SH .ie n .in 4m .el .in 8m .. .ZJ 3m 1m "1\&." NAME .in -4m .ZJ 3m 1m "2\&." SYNOPSIS .in -4m .ZJ 3m 1m "3\&." DESCRIPTION .in -4m .ZJ 3m 1m "4\&." OPTIONS .in -4m .ZJ 3m 1m "5\&." SESSION MACROS .in -4m .ZJ 3m 1m "6\&." THE SET MODIFIERS .in -4m .ZJ 3m 1m "7\&." THE INSPECT SUBLANGUAGE .in -4m .ZJ 3m 1m "8\&." THE TR SUBLANGUAGE .in -4m .ZJ 3m 1m "9\&." TILDE EXPANSION .in -4m .ZJ 3m 1m "10\&." ENVIRONMENT .in -4m .ZJ 3m 1m "11\&." DIAGNOSTICS .in -4m .ZJ 3m 1m "12\&." BUGS .in -4m .ZJ 3m 1m "13\&." SEE ALSO .in -4m .ZJ 3m 1m "14\&." EXAMPLES .in -4m .ZJ 3m 1m "15\&." AUTHOR .in -4m .SH NAME zoem \- macro processor for the Zoem macro/programming language\&. .SH SYNOPSIS \fBzoem\fP \fB[-i\fP [\&.azm] (\fIentry file name\fP)\fB]\fP \fB[-I\fP (\fIentry file name\fP)\fB]\fP \fB[-o\fP (\fIoutput file name\fP)\fB]\fP \fB[-d\fP (\fIset device key\fP)\fB]\fP \fBzoem\fP .br (enter interactive mode - happens when none of \fB-i\fP, \fB-I\fP, \fB-o\fP is given) \fBzoem\fP \fB-i\fP [\&.azm] (\fIentry file name\fP) \fB-I\fP (\fIentry file name\fP) \fB[-o\fP (\fIoutput file name\fP)\fB]\fP \fB[-d\fP (\fIset device key\fP)\fB]\fP \fB[-x\fP (\fIenter interactive mode on error\fP)\fB]\fP \fB[-s\fP [=] (\fIset key to val\fP)\fB]\fP \fB[-e\fP (\fIevaluate any, exit\fP)\fB]\fP \fB[-E\fP (\fIevaluate any, proceed\fP)\fB]\fP \fB[-chunk-size\fP (\fIprocess chunks of size num\fP)\fB]\fP \fB[--trace\fP (\fItrace mode, default\fP)\fB]\fP \fB[--trace-all-long\fP (\fIlong trace mode\fP)\fB]\fP \fB[--trace-all-short\fP (\fIshort trace mode\fP)\fB]\fP \fB[--trace-regex\fP (\fItrace regexes\fP)\fB]\fP \fB[-trace\fP k (\fItrace mode, explicit\fP)\fB]\fP \fB[--stats\fP (\fIshow symbol table stats after run\fP)\fB]\fP \fB[--split\fP (\fIassume \ewriteto usage, set \e__split__\fP)\fB]\fP \fB[--stress-write\fP (\fImake \ewrite#3 recover\fP)\fB]\fP \fB[--unsafe\fP (\fIprompt for \esystem#3\fP)\fB]\fP \fB[--unsafe-silent\fP (\fIsimply allow \esystem#3\fP)\fB]\fP \fB[-allow\fP cmd1[:cmdx]+ (\fIallowable commands\fP)\fB]\fP \fB[--system-honor\fP (\fIrequire \esystem#3 to succeed\fP)\fB]\fP \fB[-nuser\fP k (\fIuser dict stack size\fP)\fB]\fP \fB[-nenv\fP k (\fIenvironment dict stack size\fP)\fB]\fP \fB[-nsegment\fP k (\fImaximum simple nesting depth\fP)\fB]\fP \fB[-nstack\fP k (\fImaximum eval nesting depth\fP)\fB]\fP \fB[-buser\fP (\fIinitial user dict capacity\fP)\fB]\fP \fB[-bzoem\fP (\fIinitial zoem dict capacity\fP)\fB]\fP \fB[-tl\fP k (\fItab length\fP)\fB]\fP \fB[-l\fP (\fIlist items\fP)\fB]\fP \fB[-h\fP (\fIshow options\fP)\fB]\fP \fB[--apropos\fP (\fIshow options\fP)\fB]\fP .SH DESCRIPTION Zoem is a macro/programming language\&. It is fully described in the \fIZoem User Manual\fP (zum\&.html), currently available in HTML only\&. This manual page documents the zoem processor, not the zoem language\&. If the input file is specified using the \fB-i\fP option and is a regular file (i\&.e\&. not STDIN - which is specified by using a single hyphen), it must have the extension \fC\&.azm\fP\&. This extension can but need not be specified\&. The zoem key \fB\e__fnbase__\fP will be set to the file base name stripped of the \fC\&.azm\fP extension and any leading path components\&. If the input file is specified using the \fB-I\fP option, no extension is assumed, and \fB\e__fnbase__\fP is set to the file base name, period\&. The file base name is the file name with any leading path components stripped away\&. If neither \fB-i\fP nor \fB-o\fP is specified, zoem enters interactive mode\&. Zoem should fully recover from any error it encounters in the input\&. If you find an exception to this rule, consider filing a bug report\&. In interactive mode, zoem start interpreting once it encounters a line containing a single dot\&. Zoem\&'s input behaviour can be modified by setting the key \fB\e__parmode__\fP\&. See the section \fBSESSION MACROS\fP for the details\&. In interactive mode, zoem does \fInot\fP preprocess the interactive input, implying that it does not accept inline files and it does not recognize comments\&. Both types of sequence will generate syntax errors\&. Finally, readline editing and history retrieval can be used in interactive mode provided that they are available on the system\&. This means that the input lines can be retrieved, edited, and discarded with a wide range of cursor positioning and text manipulation commands\&. From within the entry file and included files it is possible to open and write to arbitrary files using the \fB\ewrite#3\fP primitive\&. Arbitrary files can be read in various modes using the \fB\edofile#2\fP macro (providing four different modes with respect to file existence and output), \fB\efinsert#1\fP, and \fB\ezinsert#1\fP\&. Zoem will write the default output to a single file, the name of which is either specified by the \fB-o\fP option, or constructed as described below\&. Zoem can split the default output among multiple files\&. This is governed from within the input files by issuing \fB\ewriteto#1\fP calls\&. Refer to the \fB--split\fP option and the \fIZoem User Manual\fP\&. If none of \fB-i\fP or \fB-o\fP is given, then zoem will enter interactive mode\&. In this mode, zoem interprets by default chunks of text that are ended by a single dot on a line of its own\&. This can be useful for testing or debugging\&. In interactive mode, zoem should recover from any failure it encounters\&. Interactive mode can also be accessed from within a file by issuing \fC\ezinsert{stdia}\fP, and it can be triggered as the mode to enter should an error occur (by adding the \fB-x\fP option to the command line)\&. If \fB-o\fP is given and \fB-i\fP is not, zoem reads input from STDIN\&. If \fB-i\fP is given and \fB-o\fP is not, zoem will construct an output file name as follows\&. If the \fB-d\fP option was used with argument \fC\fP, zoem will write to the file which results from expanding \fB\e__fnbase__\&.\fP\&. Otherwise, zoem writes to (the expansion of) \fB\e__fnbase__\&.ozm\fP\&. For \fB-i\fP and \fB-o\fP, the argument \fC-\fP is interpreted as respectively \fCstdin\fP and \fCstdout\fP\&. .SH OPTIONS .ZI 2m "\fB-i\fP [\&.azm] (\fIentry file name\fP)" \& .br Specify the entry file name\&. The file must have the \fC\&.azm\fP extension, but it need not be specified\&. .in -2m .ZI 2m "\fB-I\fP [\&.azm] (\fIentry file name\fP)" \& .br Specify the entry file name, without restrictions on the file name\&. .in -2m .ZI 2m "\fB-o\fP (\fIoutput file name\fP)" \& .br Specify the output file name\&. .in -2m .ZI 2m "\fB-d\fP (\fIset key \e__device__\fP)" \& .br Set the key \fB\e__device__\fP to \fC\fP\&. .in -2m .ZI 2m "\fB-x\fP (\fIenter interactive mode on error\fP)" \& .br The afterlife option\&. If zoem encounters an error during regular processing, it will emit error messages as usual, and then enter interactive mode\&. This allows you e\&.g\&. to inspect the values of keys used or defined within the problematic area\&. .in -2m .ZI 2m "\fB-s\fP [=] (\fIset key to val\fP)" \& .br Set the key \fB\ekey\fP to \fBval\fP if present, \fB1\fP otherwise\&. Any type of key can be set, including keys taking arguments and keys surrounded in quotes\&. Beware of the shell\&'s quote and backslash interpolation\&. Currently \fBval\fP is not evaluated, so appending or prepending to a key is not possible\&. .in -2m .ZI 2m "\fB-e\fP (\fIevaluate any, exit\fP)" \& .br This causes zoem to evaluate \fC\fP, write any result text to stdout, and exit\&. .in -2m .ZI 2m "\fB-E\fP (\fIevaluate any, proceed\fP)" \& .br This causes zoem to evaluate \fC\fP, write any result text to stdout, and proceed e\&.g\&. with the entry file or an interactive session\&. .in -2m .ZI 2m "\fB-chunk-size\fP (\fIprocess chunks of size num\fP)" \& .br Zoem reads its input in chunks\&. It fully processes a chunk before moving on with the next one\&. This option defines the (minimum) size of the chunks\&. The size or count of the chunks does not at all affect zoem\&'s output\&. The default minimum chunk size equals one megabyte\&. Zoem will read files in their entirety before further processsing if \fB-chunk-size\fP\ \&\fB0\fP is specified\&. Zoem does not chunk input files arbitrarily\&. It will append to a chunk until it is in the outermost scope (not contained within any block) and the chunk will end with a line that was fully read\&. Consequently, if e\&.g\&. a file contains a block (delimited by balanced curlies) spanning the entire file then zoem is forced to read it in its entirety\&. .in -2m .ZI 2m "\fB--trace\fP (\fItrace mode, default\fP)" \& .br Trace in default mode\&. .in -2m .ZI 2m "\fB--trace-all-long\fP (\fIlong trace mode\fP)" \& .br Sets on \fImost\fP trace options in long mode\&. Trace options \fCxxx\fP not set have their own \fB--trace-xxx\fP entry (see below)\&. .in -2m .ZI 2m "\fB--trace-all-short\fP (\fIshort trace mode\fP)" \& .br Sets on \fImost\fP trace options in short mode\&. Trace options \fCxxx\fP not set have their own \fB--trace-xxx\fP entry (see below)\&. .in -2m .ZI 2m "\fB--trace-keys\fP (\fItrace keys\fP)" \& .br Trace keys\&. .in -2m .ZI 2m "\fB--trace-regex\fP (\fItrace regexes\fP)" \& .br Trace regexes (i\&.e\&. the \fB\einspect#4\fP primitive)\&. .in -2m .ZI 2m "\fB-trace\fP k (\fItrace mode, explicit\fP)" \& .br Set trace options by adding their representing bits\&. .in -2m .ZI 2m "\fB--stress-write\fP (\fIstress test using write\fP)" \& .br This makes \fB\ewrite#3\fP recover from errors\&. It is a special purpose option used for creating zoem stress test suites, such as \fCstress\&.azm\fP in the zoem distribution \fC/examples\fP subdirectory\&. .in -2m .ZI 2m "\fB--unsafe\fP (\fIprompt for \esystem#3\fP)" \& 'in -2m .ZI 2m "\fB--unsafe-silent\fP (\fIsimply allow \esystem#3\fP)" \& 'in -2m .ZI 2m "\fB-allow\fP cmd1[:cmdx]+ (\fIallowable commands\fP)" \& 'in -2m 'in +2m \& .br With \fB--unsafe\fP system calls are allowed but the user is prompted for each invocation\&. The command and its arguments (if any) are shown, but the STDIN information (if any) is withheld\&. With \fB--unsafe-silent\fP system calls are allowed and the user is never prompted\&. Use \fB-allow\fP\ \&\fIstr\fP or \fB--allow\fP=\fIstr\fP to specify a list of allowable commands, as a string in which the commands are separated by colons\&. .in -2m .ZI 2m "\fB--system-honor\fP (\fIrequire \esystem#3 to succeed\fP)" \& .br With this option any \fC\esystem#3\fP failure (for whatever reason, including safe behaviour) is regarded as a zoem failure\&. By default, failing system calls are ignored under either safe mode, unsafe mode (--unsafe), or silent unsafe mode (--unsafe-silent)\&. .in -2m .ZI 2m "\fB--split\fP (\fIassume split output\fP)" \& .br This assumes zoem input that allows output to multiple files (e\&.g\&. chapters)\&. It sets the default output stream to \fCstdout\fP (anticipating custom output redirection with \fB\ewriteto#1\fP) and sets the session macro \fB\e__split__\fP to \fC1\fP\&. .in -2m .ZI 2m "\fB--stats\fP (\fIshow symbol table stats after run\fP)" \& .br Show symbol table chacteristics\&. Symbol tables are maintained as hashes\&. .in -2m .ZI 2m "\fB-tl\fP k (\fIset tab length\fP)" \& .br Set the tab length\&. HTML output can be indented according to nesting structure, using tabs which are expanded to simple spaces\&. By default, the tab length is zero, meaning that no indent is shown\&. The maximum value the tab length can be set to is four\&. .in -2m .ZI 2m "\fB-nsegment\fP k (\fIlevel of macro nesting allowed\fP)" \& 'in -2m .ZI 2m "\fB-nstack\fP k (\fIstack count\fP)" \& 'in -2m .ZI 2m "\fB-nuser\fP k (\fIuser dictionary stack size\fP)" \& 'in -2m .ZI 2m "\fB-nenv\fP k (\fIenvironment dictionary stack size\fP)" \& 'in -2m .ZI 2m "\fB-buser\fP k (\fIinitial user dict capacity\fP)" \& 'in -2m .ZI 2m "\fB-bzoem\fP k (\fIinitial zoem dict capacity\fP)" \& 'in -2m 'in +2m \& .br Probably needed only if you have some obscure and extreme use for zoem\&. The segment limit applies to simple nesting of macros\&. The stack limit applies to nesting of macros that evaluate an argument before use\&. Each such evaluation creates a new stack\&. The user limit applies to \fB\epush{user}\fP, the env limit applies to the nesting level of environments (started with \fC\ebegin#2\fP)\&. The user dict capacity pertains to the initial number of buckets allocated for user and environment dictionaries, and the zoem dict capacity pertains to the dictionary containing the zoem primitives\&. .in -2m .ZI 2m "\fB-l\fP (\fIlist items\fP)" \& .br List items identified by \fC\fP\&. It can be any of \fBall\fP, \fBfilter\fP\&. \fBlegend\fP, \fBbuiltin\fP, \fBsession\fP, \fBtrace\fP, or \fBzoem\fP, Multiple identifiers can be joined in a string, e\&.g\&. \fC-l legendzoem\fP prints a legend followed by a listing of zoem primitives\&. .in -2m .ZI 2m "\fB-h\fP (\fIshow options\fP)" \& .br Show short synopsis of options\&. .in -2m .SH SESSION MACROS .ZI 2m "\fB\e__parmode__\fP" \& .br This macro affects zoem\&'s read behaviour in interactive mode\&. It can be set on the command line using the \fB-s\fP option\&. Bits that can be set: .di ZV .in 0 .nf \fC 1 chomp newlines (remove the newline character) 2 skip empty newlines 4 read paragraphs (an empty line triggers input read) 8 newlines can be escaped using a backslash 16 read large paragraphs (a single dot on a line triggers input read) .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR .in -2m .ZI 2m "\fB\e__device__\fP" \& .br The current output device, set by the command line option \fB-d\fP\&. The \fBman\fP and \fBfaq\fP packages support \fBhtml\fP and \fBroff\fP as its values\&. .in -2m .ZI 2m "\fB\e__fnbase__\fP" \& .br The base name of the input file name\&. Leading path components are stripped away\&. If the \fB-i\fP option is used the input file is required to have the \fC\&.azm\fP suffix\&. In that case the suffix is also stripped to obtain the base name\&. .in -2m .ZI 2m "\fB\e__fnentry__\fP" \& .br The name of the entry file\&. .in -2m .ZI 2m "\fB\e__fnin__\fP" \& .br The file currently being processed\&. .in -2m .ZI 2m "\fB\e__fnout__\fP" \& .br The name of the default output file\&. .in -2m .ZI 2m "\fB\e__fnpath__\fP" \& .br The leading component of the input file name, possibly empty\&. .in -2m .ZI 2m "\fB\e__fnup__\fP" \& .br The file that included the current file, if applicable\&. .in -2m .ZI 2m "\fB\e__fnwrite__\fP" \& .br This key is set by \fC\ewrite#3\fP to its first argument\&. It can be used by macros that are expanded during evaluation of the third argument\&. Possible usage is to branch on the name of the \fIwrite\fP output stream\&. For example a file called \fIindex\&.html\fP may be treated differently from other files\&. The key is deleted afterwards\&. Nested invocations of \fC\ewrite#3\fP may corrupt the status of this key\&. .in -2m .ZI 2m "\fB\e__ia__\fP" \& .br The input/output separator used in interactive mode\&. .in -2m .ZI 2m "\fB\e__line__\fP" \& .br The line number in the file currently being processed\&. This number will be correct for any invocation outside the scope of a macro\&. For any invocation within a macro the result will be the line number of the closing curly of the outermost containing macro\&. The following .di ZV .in 0 .nf \fC \e__line__ \e__line__ \e__line__ \egroup{ \e__line__ \egroup{\e__line__} \e__line__} .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR Results in .di ZV .in 0 .nf \fC 1 2 3 7 7 7 .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR .in -2m .ZI 2m "\fB\e__searchpath__\fP" \& .br A vararg containing a list of paths to search when a file is to be included/imported/read/loaded\&. When you start zoem, this key should contain the location of the \fBman\&.zmm\fP and \fBfaq\&.zmm\fP package files\&. It is advisable not to overwrite this key but to append to it instead\&. .in -2m .ZI 2m "\fB\e__zoemstat__\fP" \& .br Set to one of \fCok\fP, \fCtowel\fP (that one is a bit lame), or \fCerror\fP by either the interpreter, an occurrence of \fC\ecatch#2\fP, or \fC\etry#1\fP\&. .in -2m .ZI 2m "\fB\e__zoemput__\fP" \& .br Set by \fC\etry#1\fP to the possibly truncated result of processing its argument\&. .in -2m .ZI 2m "\fB\e__lc__\fP" \& .br Expands to a left curly\&. It is hard to find a need for this \- the zoem stress suite uses it to generate a particular syntax error at a deeper interpretation level\&. .in -2m .ZI 2m "\fB\e__rc__\fP" \& .br Expands to a right curly\&. .in -2m .SH THE SET MODIFIERS The \fC\eset#3\fP primitive allows a \fC{modes}{}\fP directive in its first argument\&. Here \fI\fP can be a combination of single-letter modifiers, each described below\&. .ZI 2m "a" append to the key, do not overwrite, create if not existing\&. .in -2m .ZI 2m "c" conditionally; only set if not already defined\&. .in -2m .ZI 2m "e" existing; update existing key, possibly in lower dictionary\&. .in -2m .ZI 2m "g" global; set in the global (bottom) user dictionary\&. .in -2m .ZI 2m "u" unary; do not interpret vararg in \fC\fP as key-value list (data keys only) .in -2m .ZI 2m "v" vararg; interpret vararg in \fC\fP as key-value list (regular keys only)\&. .in -2m .ZI 2m "w" warn if key exists (like \fC\edef#2\fP and \fC\edefx#2\fP)\&. .in -2m .ZI 2m "x" expand argument (like \fC\esetx#2\fP and \fC\edefx#2\fP)\&. .in -2m .SH THE INSPECT SUBLANGUAGE The \fC\einspect#4\fP primitive takes four arguments\&. The languages accepted by the first two arguments are described below\&. The third argument is a replacement string or a replacement macro accepting back-references (supplied as an anonymous macro)\&. The fourth argument is the data to be processed\&. \fBarg 1\fP .br Is a vararg\&. Currently it accepts a single key \fImods\fP for which the value should be a comma-separated list over the words \fIposix\fP, \fIicase\fP, \fIdotall\fP, \fIiter-lines\fP \fIiter-args\fP, \fImatch-once\fP, \fIdiscard-nmp\fP, \fIdiscard-nil-out\fP, \fIdiscard-miss\fP, \fIcount-matches\fP\&. Alternatively repeated use of \fImods\fP is allowed\&. \fBarg 2\fP .br Is a regular expression\&. Tilde patterns are expanded according to all of the ZOEM, UNIX, and REGEX schemes\&. Refer to \fBTILDE EXPANSION\fP for these\&. The third argument is a constant string or an anonymous key, the fourth argument is data\&. .SH THE TR SUBLANGUAGE The \fC\etr#2\fP primitive takes two arguments\&. The first argument contains key-value pairs\&. The accepted keys are \fIfrom\fP and \fIto\fP which must always occur together, and \fIdelete\fP and \fIsquash\fP\&. The values of these keys must be valid \fItranslation\fP specifications\&. This primitive transforms the data in the second argument by successively applying translation, deletion and squashing in that order\&. Only the transformations that are needed need be specified\&. Translation specifications are subjected to UNIX tilde expansion as described below\&. The syntax accepted by translation specifications is almost fully compliant with the syntax accepted by \fBtr\fP(1), with three exceptions\&. First, repeats are introduced as \fC[*a*20]\fP rather than \fC[a*20]\fP\&. Second, ranges can (for now) only be entered as \fCX-Y\fP, not as \fC[X-Y]\fP\&. \fCX\fP and \fCY\fP \fIcan\fP be entered in either octal or hexadecimal notation (see further below)\&. As an additional feature, the magic repeat operator \fC[*a#]\fP stops on both class and range boundaries\&. Character specifications can be complemented by preceding them with the caret \fC^\fP\&. Specifications may contain ranges of characters such as \fCa-z\fP and \fC0-9\fP\&. Posix character classes are allowed\&. The available classes are .di ZV .in 0 .nf \fC [:alnum:] [:alpha:] [:cntrl:] [:digit:] [:graph:] [:lower:] [:print:] [:punct:] [:space:] [:upper:] [:xdigit:] .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR Characters can be specified using octal notation, e\&.g\&. \fC\e012\fP encodes the newline\&. Use \fC\e173\fP for the opening curly, \fC\e175\fP for the closing curly, \fC\e134\fP for the backslash, and \fC\e036\fP for the caret if it is the first character in a specification\&. \fIDON\&'T\fP use \fC\e\e\fP, \fC\e{\fP, or\ \&\fC\e}\fP in this case! Hexadecimal notation is written as \fC\ex7b\fP (the left curly in this instance)\&. See \fBEXAMPLES\fP for an example of \fCtr#2\fP usage\&. .SH TILDE EXPANSION Some primitives interface with UNIX libraries that require backslash escape sequences to encode certain tokens or characters\&. The backslash is special in zoem too and without further measures it can become very cumbersome to encode the correct escape sequences as it is not always clear which tokens should be escaped or unprotected at what point\&. It is especially difficult to handle the zoem characters with special meaning, \fC{\fP, \fC}\fP and \fC\e\fP\&. The two primitives under consideration are \fB\einspect#4\fP and \fB\etr#2\fP\&. Both treat the tilde as an additional escape character for certain arguments (as documented in the user manual)\&. These arguments are subjected to tilde expansion, where the tilde and the character it proceeds are translated to a new character or character sequence\&. There are three different sets of tilde escapes, ZOEM, UNIX and REGEX escapes\&. \fB\etr#2\fP only accepts UNIX escapes, \fB\einspect#4\fP accepts all\&. Tilde expansion is always the last processing step before strings are passed on to external libraries\&. The ZOEM scheme contains some convenience escapes, such as \fC~E\fP to encode a double backslash\&. \fBZOEM tilde expansion\fP .nf \fC \fB meta sequence replacement \&.-----------------------------\&. | ~~ | ~ | | ~E | \e\e | | ~e | \e | | ~I | \e{ | | ~J | \e} | | ~x | \ex | | ~i | { | | ~j | } | \&`-----------------------------\&'\fP .fi \fR The zoem tr specification language accepts \fC\ex**\fP as hexadecimal notation, e\&.g\&. \fC\ex0a\fP denotes a newline in the ASCII character set\&. \fBUNIX tilde expansion\fP .nf \fC \fB meta sequence replacement \&.-----------------------------\&. | ~a | \ea | | ~b | \eb | | ~f | \ef | | ~n | \en | | ~r | \er | | ~t | \et | | ~v | \ev | | ~0 | \e0 | | ~1 | \e1 | | ~2 | \e2 | | ~3 | \e3 | \&`-----------------------------\&'\fP .fi \fR \fBREGEX tilde expansion\fP .nf \fC \fB meta sequence replacement \&.-----------------------------\&. | ~^ | \e^ | | ~\&. | \e\&. | | ~[ | \e[ | | ~$ | \e$ | | ~( | \e( | | ~) | \e) | | ~| | \e| | | ~* | \e* | | ~+ | \e+ | | ~? | \e? | \&`-----------------------------\&'\fP .fi \fR .SH ENVIRONMENT The environment variable ZOEMSEARCHPATH may contain a colon and/or whitespace separated list of paths\&. It will be used when searching for files included via one of the \fCdofile\fP aliases \fC\einput\fP, \fC\eimport\fP, \fC\eread\fP, and \fC\eload\fP\&. Note that the zoem macro \fC\e__searchpath__\fP contains the location where the zoem macro files were copied at the time of installation of zoem\&. .SH DIAGNOSTICS On error, Zoem prints a file name and a line number to which it was able to trace the error\&. The number reported is the same as the one stored in the session macro \fC\e__line__\fP\&. For an error-trigering macro which is not nested within another macro the line number should be correct\&. For a macro that does occur nested within another macro the line number will be the line number of the closing curly in the outermost containing macro\&. If in despair, use one of the tracing modes, \fB--trace-keys\fP is one of the first to come to mind\&. Another possibility is to supply the \fB-x\fP option\&. .SH BUGS No known bugs\&. \fB\einspect#4\fP has not received thorough stress-testing, and the more esoteric parts of its interface will probably change\&. .SH SEE ALSO \fIAephea\fP is a document authoring framework largely for HTML documents\&. \fIPortable Unix Documentation\fP provides two mini-languages for authoring in the unix environment\&. These languages, pud-man and pud-faq are both written in zoem\&. .SH EXAMPLES This is a relatively new section, aimed at assembling useful or explanatory snippets\&. Create a vararg containing file names matching a pattern (\fCpng\fP in this example)\&. .di ZV .in 0 .nf \fC \esetx{images}{ \einspect{ {mods}{iter-lines,discard-miss} }{(\&.*~\&.png)}{_#1{{\e1}}}{\esystem{ls}} } .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR Use magic boundary stops with \fCtr#2\fP\&. .di ZV .in 0 .nf \fC \etr{ {from}{[:lower:][:upper:][:digit:][:space:][:punct:]} {to}{[*L#][*U#][*D#][*S#][*P#]}}{ !"#$%&\&'()*+,-\&./0123456789:;<=>?@ ABCDEFGHIJKLMNOPQRSTUVWXYZ [\e\e]^_\&` abcdefghijklmnopqrstuvwxyz \e{|\e}~]} .fi \fR .in .di .ne \n(dnu .nf \fC .ZV .fi \fR .SH AUTHOR Stijn van Dongen\&. zoem-11-166/doc/stamp.year0000644000402500021140000000000511576203373012250 000000000000002011 zoem-11-166/doc/stamp.month0000644000402500021140000000000411576203373012434 00000000000000Jun zoem-11-166/doc/stamp.day0000644000402500021140000000000311576203373012063 0000000000000015 zoem-11-166/doc/stamp.stamp0000644000402500021140000000000711576203373012436 0000000000000011-166 zoem-11-166/examples/0000777000402500021140000000000011576212302011374 500000000000000zoem-11-166/examples/README0000644000402500021140000000421210041035061012156 00000000000000 Each pair of files name.azm name.ozm demonstrates one or more concepts from the zoem language. Basic processing for file 'name.azm' zoem -i name results in the output file 'name.ozm'. Some files need additional processing flags, these are indicated below and can be found in the Makefile as well. The file fib.azm demonstrates how to include input interactively, so there is no matching 'fib.ozm' file. The file stress.azm contains a large set of error tests from which zoem must be able to recover fully - it should in general recover from almost any conceivable error. In stress.azm this is done via \catch{error}{.. erroneous stuf ..}. In interactive mode, zoem will recover from errors without any help. Zoem can enter interactive mode upon errors in regular file processing via the -x option. DESCRIPTION ------------------------------------------------------------------------------ catch.azm nested while{1}{...} stopped by throwing exception. fib.azm prompting and inclusion via STDIN, while{} stuff. loop.azm nested apply invocations. meta.azm zoem 'closure' mechanism of some sort. nest.azm anon/nesting/delay arithmetic, not very instructive. power-of-2.azm computing 2*k by recursion and file size. reverse.azm how to revert (nested!) lists with zoem. scope.azm basic illustration of push/pop name scopes. special.azm silly illustration of filtering capabilities. stress.azm extensive stress test suite. tr.azm some translate options, not very interesting. txt-table.azm text formatting examples. xml.azm *ML syntactic sugar examples. ADDITIONAL OPTIONS NEEDED ------------------------------------------------------------------------------ stress.azm --err-out -o - --allow=date:#:ls power-of-2.azm --allow=ls [-s level=] xml.azm -tl 3 fib.azm -o - zoem-11-166/examples/Makefile.am0000644000402500021140000000253011574125210013343 00000000000000## Process this file with automake to produce Makefile.in # $Id: Makefile.am,v 1.15 2005/06/30 16:23:25 flux Exp $ docdir = $(datadir)/doc/$(PACKAGE) docexamplesdir = $(docdir)/examples docexamples_DATA = \ README \ 8q.azm 8q.ozm \ 8q2.azm 8q2.ozm \ power-of-2.azm power-of-2.ozm \ catch.azm catch.ozm \ fib.azm \ loop.azm loop.ozm \ meta.azm meta.ozm \ nest.azm nest.ozm \ reverse.azm reverse.ozm \ scope.azm scope.ozm \ special.azm special.ozm \ stress.azm stress.reg \ stress2.azm stress2.reg \ tr.azm tr.ozm \ txt-table.azm txt-table.ozm \ xml.azm xml.ozm EXTRA_DIST = README Makefile $(docexamples_DATA) SUFFIXES = .azm .ozm .azm.ozm: ../src/zoem -i $< -o $@ # fib.azm is for demonstration of interactive behaviour. fib.ozm: fib.azm true stress.ozm: stress.azm ../src/zoem -i stress --system-honor --unsafe-silent --err-out -s get_it_on=1 -o - > stress.ozm stress2.ozm: stress2.azm ../src/zoem -i stress2 --system-honor --unsafe-silent --err-out -s get_it_on=1 -o - > stress2.ozm power-of-2.ozm: power-of-2.azm ../src/zoem -i power-of-2 --allow=ls xml.ozm: xml.azm ../src/zoem -i xml -tl 3 sys1: zoem -i system -o - --allow=date sys2: zoem -i system -o system.ozm --allow=date sys3: zoem -i system -o - --allow=date > system.ozm zoem-11-166/examples/Makefile.in0000644000402500021140000002763611576203400013372 00000000000000# Makefile.in generated by automake 1.11 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ # $Id: Makefile.am,v 1.15 2005/06/30 16:23:25 flux Exp $ VPATH = @srcdir@ 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 = : subdir = examples DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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 = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = 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__installdirs = "$(DESTDIR)$(docexamplesdir)" DATA = $(docexamples_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_cv_use_includepath = @ac_cv_use_includepath@ 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_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = $(datadir)/doc/$(PACKAGE) dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ docexamplesdir = $(docdir)/examples docexamples_DATA = \ README \ 8q.azm 8q.ozm \ 8q2.azm 8q2.ozm \ power-of-2.azm power-of-2.ozm \ catch.azm catch.ozm \ fib.azm \ loop.azm loop.ozm \ meta.azm meta.ozm \ nest.azm nest.ozm \ reverse.azm reverse.ozm \ scope.azm scope.ozm \ special.azm special.ozm \ stress.azm stress.reg \ stress2.azm stress2.reg \ tr.azm tr.ozm \ txt-table.azm txt-table.ozm \ xml.azm xml.ozm EXTRA_DIST = README Makefile $(docexamples_DATA) SUFFIXES = .azm .ozm all: all-am .SUFFIXES: .SUFFIXES: .azm .ozm $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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 examples/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu examples/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-docexamplesDATA: $(docexamples_DATA) @$(NORMAL_INSTALL) test -z "$(docexamplesdir)" || $(MKDIR_P) "$(DESTDIR)$(docexamplesdir)" @list='$(docexamples_DATA)'; test -n "$(docexamplesdir)" || list=; \ 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)$(docexamplesdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docexamplesdir)" || exit $$?; \ done uninstall-docexamplesDATA: @$(NORMAL_UNINSTALL) @list='$(docexamples_DATA)'; test -n "$(docexamplesdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(docexamplesdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(docexamplesdir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: 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 check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(docexamplesdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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 mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-docexamplesDATA 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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-docexamplesDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-docexamplesDATA 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 pdf \ pdf-am ps ps-am uninstall uninstall-am \ uninstall-docexamplesDATA .azm.ozm: ../src/zoem -i $< -o $@ # fib.azm is for demonstration of interactive behaviour. fib.ozm: fib.azm true stress.ozm: stress.azm ../src/zoem -i stress --system-honor --unsafe-silent --err-out -s get_it_on=1 -o - > stress.ozm stress2.ozm: stress2.azm ../src/zoem -i stress2 --system-honor --unsafe-silent --err-out -s get_it_on=1 -o - > stress2.ozm power-of-2.ozm: power-of-2.azm ../src/zoem -i power-of-2 --allow=ls xml.ozm: xml.azm ../src/zoem -i xml -tl 3 sys1: zoem -i system -o - --allow=date sys2: zoem -i system -o system.ozm --allow=date sys3: zoem -i system -o - --allow=date > system.ozm # 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: zoem-11-166/examples/Makefile0000644000402500021140000003021611576203460012757 00000000000000# Makefile.in generated by automake 1.11 from Makefile.am. # examples/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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. # $Id: Makefile.am,v 1.15 2005/06/30 16:23:25 flux Exp $ pkgdatadir = $(datadir)/zoem pkgincludedir = $(includedir)/zoem pkglibdir = $(libdir)/zoem pkglibexecdir = $(libexecdir)/zoem 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 = : subdir = examples DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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 = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = 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__installdirs = "$(DESTDIR)$(docexamplesdir)" DATA = $(docexamples_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /homes/stijn/topaz/micans/zoem/zoem/missing --run aclocal-1.11 AMTAR = ${SHELL} /homes/stijn/topaz/micans/zoem/zoem/missing --run tar AUTOCONF = ${SHELL} /homes/stijn/topaz/micans/zoem/zoem/missing --run autoconf AUTOHEADER = ${SHELL} /homes/stijn/topaz/micans/zoem/zoem/missing --run autoheader AUTOMAKE = ${SHELL} /homes/stijn/topaz/micans/zoem/zoem/missing --run automake-1.11 AWK = gawk CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CPP = gcc -E CPPFLAGS = CYGPATH_W = echo DEFS = -DHAVE_CONFIG_H DEPDIR = .deps ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E EXEEXT = GREP = /bin/grep INSTALL = /usr/bin/install -c INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s LDFLAGS = LIBOBJS = LIBS = -lreadline -ltermcap LN_S = ln -s LTLIBOBJS = MAINT = # MAKEINFO = ${SHELL} /homes/stijn/topaz/micans/zoem/zoem/missing --run makeinfo MKDIR_P = /bin/mkdir -p OBJEXT = o PACKAGE = zoem PACKAGE_BUGREPORT = stijn@micans.org PACKAGE_NAME = zoem PACKAGE_STRING = zoem 11-166 PACKAGE_TARNAME = zoem PACKAGE_URL = PACKAGE_VERSION = 11-166 PATH_SEPARATOR = : RANLIB = ranlib SET_MAKE = SHELL = /bin/sh STRIP = VERSION = 11-166 abs_builddir = /homes/stijn/topaz/micans/zoem/zoem/examples abs_srcdir = /homes/stijn/topaz/micans/zoem/zoem/examples abs_top_builddir = /homes/stijn/topaz/micans/zoem/zoem abs_top_srcdir = /homes/stijn/topaz/micans/zoem/zoem ac_ct_CC = gcc ac_cv_use_includepath = /foo/bar:/homes/stijn/local/share/aephea am__include = include am__leading_dot = . am__quote = am__tar = ${AMTAR} chof - "$$tardir" am__untar = ${AMTAR} xf - bindir = ${exec_prefix}/bin build_alias = builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = $(datadir)/doc/$(PACKAGE) dvidir = ${docdir} exec_prefix = ${prefix} host_alias = htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /homes/stijn/topaz/micans/zoem/zoem/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var mandir = ${datarootdir}/man mkdir_p = /bin/mkdir -p oldincludedir = /usr/include pdfdir = ${docdir} prefix = /homes/stijn/local program_transform_name = s,x,x, psdir = ${docdir} sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../ top_builddir = .. top_srcdir = .. docexamplesdir = $(docdir)/examples docexamples_DATA = \ README \ 8q.azm 8q.ozm \ 8q2.azm 8q2.ozm \ power-of-2.azm power-of-2.ozm \ catch.azm catch.ozm \ fib.azm \ loop.azm loop.ozm \ meta.azm meta.ozm \ nest.azm nest.ozm \ reverse.azm reverse.ozm \ scope.azm scope.ozm \ special.azm special.ozm \ stress.azm stress.reg \ stress2.azm stress2.reg \ tr.azm tr.ozm \ txt-table.azm txt-table.ozm \ xml.azm xml.ozm EXTRA_DIST = README Makefile $(docexamples_DATA) SUFFIXES = .azm .ozm all: all-am .SUFFIXES: .SUFFIXES: .azm .ozm $(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 examples/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu examples/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): install-docexamplesDATA: $(docexamples_DATA) @$(NORMAL_INSTALL) test -z "$(docexamplesdir)" || $(MKDIR_P) "$(DESTDIR)$(docexamplesdir)" @list='$(docexamples_DATA)'; test -n "$(docexamplesdir)" || list=; \ 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)$(docexamplesdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docexamplesdir)" || exit $$?; \ done uninstall-docexamplesDATA: @$(NORMAL_UNINSTALL) @list='$(docexamples_DATA)'; test -n "$(docexamplesdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(docexamplesdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(docexamplesdir)" && rm -f $$files tags: TAGS TAGS: ctags: CTAGS CTAGS: 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 check: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(docexamplesdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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 mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-docexamplesDATA 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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-docexamplesDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am \ install-docexamplesDATA 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 pdf \ pdf-am ps ps-am uninstall uninstall-am \ uninstall-docexamplesDATA .azm.ozm: ../src/zoem -i $< -o $@ # fib.azm is for demonstration of interactive behaviour. fib.ozm: fib.azm true stress.ozm: stress.azm ../src/zoem -i stress --system-honor --unsafe-silent --err-out -s get_it_on=1 -o - > stress.ozm stress2.ozm: stress2.azm ../src/zoem -i stress2 --system-honor --unsafe-silent --err-out -s get_it_on=1 -o - > stress2.ozm power-of-2.ozm: power-of-2.azm ../src/zoem -i power-of-2 --allow=ls xml.ozm: xml.azm ../src/zoem -i xml -tl 3 sys1: zoem -i system -o - --allow=date sys2: zoem -i system -o system.ozm --allow=date sys3: zoem -i system -o - --allow=date > system.ozm # 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: zoem-11-166/examples/8q.azm0000644000402500021140000001057310713626206012363 00000000000000 \: N queens problem solved in zoem. \: This solution uses recursion (naturally), maintaining dictionaries \: with push#1 and pop#1. It also uses a crude form of iteration \: using apply#2. Failure is escalated back using throw#2 and catch#2. \: This constitutes a non-trivial example of apply#2 / throw#2 / catch#2 \: used in conjunction. \: A more customary solution is to use while#2 rather than the \: latter method -- see 8q2.azm. \: This solution has caused two zoem weak spots to be addressed: \: - inability to cleanly assign a vararg to a data key. \: -> now possible with \set{{modes}{u}}{%{key}}{{a}{b}{c}{e}{t}{c}} \: - inability to effect global key updates while dictionaries are pushed. \: -> now possible with \set{''key}{..} (and \''key access). \if{\let{!\defined{key}{N} || \N < 1}}{ \write{stderr}{device}{Use e.g. zoem -i 8q -s N=9 to solve the 9-queen problem\@{\N}} \set{N}{8} }{} \setx{N}{\let{floor(\N)}} \set{n_backtrack}{0} \set{p_backtrack}{0} \: When updating these we have to be careful \: to do it in the bottom global dictionary, \: not in a higher stacked transient dictionary. \set{%{lists}{0}}{} \set{n1}{0} \set{n}{1} \: Precompute all lists that we are going to feed \: to apply#2. This is only slightly wasteful. \while{\let{\n<=\N}}{ \: This uses recently introduced primitive set#3. \: The u modifier indicates the value argument \: should not be parsed as a key-value list. \set{{modes}{xu}}{%{lists}{\n}}{\%{lists}{\n1} {\n1}} \set{%{positions}{\n}}{} \setx{n1}{\n} \setx{n}{\let{\n+1}} } \: for shorter print statement \def{pp#1}{\%{positions}{\1}} \: \: \: 5 | . . . . . . \: 4 | . . * . . . \: 3 | . . . . ? . \: 2 | . * . . . . \: 1 | . . . * . . \: 0 | * . . . . . \: |________________________ \: col: | 4 5 6 7 \: c: 0 1 2 3 \: for c in 0..col-1 get the position and see whether it \: is compatible with col,row \formatted{ \def{testcompat#1}{ \setx{c}{\1} \if{\let{ \%{positions}{\c}==\row || \%{positions}{\c}-\row==\col-\c || \%{positions}{\c}-\row==\c-\col } }{\setx{''n_backtrack}{\let{\''n_backtrack+1}} \throw{towel}{} }{} } \: Try whether row would fit col. \def{testrow#1}{ \push{testrow} \setx{row}{\1} \catch{towel}{ \apply{testcompat#1}{\%{lists}{\col}} } \: Alternative is to use \while rather than apply+catch \: still, timing seems to be OK for this approach. \if{\cmp{eq}{\__zoemstat__}{done}}{ \setx{%{positions}{\col}}{\row} \if{\let{\col<\N-1}}{ \extendcol{\let{\col+1}} }{ \write{\__fnout__}{device}{\@{\N}\pp{0}} \set{t}{1} \while{\let{\t<\N}}{ \write{\__fnout__}{device}{\`{s}\pp{\t}} \setx{t}{\let{\t+1}} } \setx{d_bt}{\let{\''n_backtrack-\''p_backtrack}} \write{\__fnout__}{device}{\ifdef{key}{trace}{\`{s}(\''n_backtrack, \d_bt)}\@{\n}} \setx{''p_backtrack}{\''n_backtrack} } }{} \pop{testrow} } \: 0..col-1 columns are OK \: Try to extend to column col. \def{extendcol#1}{ \push{extendcol} \setx{col}{\1} \apply{testrow#1}{\%{lists}{\N}} \pop{extendcol} } } \: vanish#1 omits the filter/output stage in an attempt \: to gain some speed -- it only results in side effects (yay!) \: such as the \write#2 invocation above. \: However, because we used formatted#1 we really don't \: gain anything as all result strings have length zero \: anyway. \vanish{\extendcol{0}} \write{stderr}{device}{Backtracked \''n_backtrack times\@{\n}} zoem-11-166/examples/8q.ozm0000644000402500021140000000106011563247651012377 000000000000000 2 4 6 1 3 5 0 3 6 2 5 1 4 0 4 1 5 2 6 3 0 5 3 1 6 4 2 1 3 0 6 4 2 5 1 3 5 0 2 4 6 1 4 0 3 6 2 5 1 4 2 0 6 3 5 1 4 6 3 0 2 5 1 5 2 6 3 0 4 1 6 4 2 0 5 3 2 0 5 1 4 6 3 2 0 5 3 1 6 4 2 4 6 1 3 5 0 2 5 1 4 0 3 6 2 6 1 3 5 0 4 2 6 3 0 4 1 5 3 0 2 5 1 6 4 3 0 4 1 5 2 6 3 1 6 4 2 0 5 3 5 0 2 4 6 1 3 6 2 5 1 4 0 3 6 4 1 5 0 2 4 0 3 6 2 5 1 4 0 5 3 1 6 2 4 1 5 2 6 3 0 4 2 0 5 3 1 6 4 6 1 3 5 0 2 4 6 1 5 2 0 3 5 0 2 4 6 1 3 5 1 4 0 3 6 2 5 2 0 3 6 4 1 5 2 4 6 0 3 1 5 2 6 3 0 4 1 5 3 1 6 4 2 0 5 3 6 0 2 4 1 6 1 3 5 0 2 4 6 2 5 1 4 0 3 6 3 0 4 1 5 2 6 4 2 0 5 3 1 zoem-11-166/examples/8q2.azm0000644000402500021140000000260511576146736012457 00000000000000 \if{\let{!\defined{key}{N} || \N < 1}}{ \write{stderr}{device}{Use e.g. zoem -i 8q2 -s N=9 to solve the 9-queen problem\@{\N}} \set{N}{8} }{} \setx{N}{\let{floor(\N)}} \def{pp#1}{\%{ass}{\1}} \set{ptr}{0} \set{%{ass}{-1}}{0} \setx{row_odd}{\seq{n}{0}{\N}{\if{\let{\n%2}}{.}{-} }} \setx{row_even}{\seq{n}{0}{\N}{\if{\let{\n%2}}{-}{.} }} \set{n}{0} \while{\let{\n<=\N}}{ \set{%{ass}{\n}}{0} \setx{n}{\let{\n+1}} } \set{n}{0} \while{\let{\n<=\N}}{ \setx{n}{\let{\n+1}} } \set{id}{0} \while{\let{\ptr>=0}}{ \set{i}{0} \while{\let{ \i<\ptr && \%{ass}{\i} != \%{ass}{\ptr} && \%{ass}{\i} - \%{ass}{\ptr} != \ptr - \i && \%{ass}{\i} - \%{ass}{\ptr} != \i - \ptr } }{\setx{i}{\let{\i+1}}} \branch{ {\let{\i==\N-1}} { \set{t}{0} \while{\let{\t<\N}}{ \setx{t2}{\if{\let{\t % 2}}{\row_odd}{\row_even}} \set{{start}{\let{2*\pp{\t}}}{width}{1}}{t2}{W} \write{\__fnout__}{device}{\t2\@{\n}} \setx{t}{\let{\t+1}} } \setx{id}{\let{\id+1}} \write{\__fnout__}{device}{(\id)\@{\P}} } {\let{\i==\ptr}} { \setx{ptr}{\let{\ptr+1}} \set{%{ass}{\ptr}}{-1} } } \while{\let{\ptr>=0 && \%{ass}{\ptr} == \N-1}}{ \set{%{ass}{\ptr}}{0} \setx{ptr}{\let{\ptr-1}} } \setx{%{ass}{\ptr}}{\let{\%{ass}{\ptr}+1}} } zoem-11-166/examples/8q2.ozm0000644000402500021140000003003711576147641012471 00000000000000W - . - . - . - - . - . W . - . . - . - . - . W - . - . - W - . . - W - . - . - - . - . - . W . . W . - . - . - - . - W - . - . (1) W - . - . - . - - . - . - W - . . - . - . - . W - . W . - . - . . - . - . - W - - . - W - . - . . W . - . - . - - . - . W . - . (2) W - . - . - . - - . - . - . W . . - . W . - . - - . - . - W - . . - . - . - . W - W - . - . - . . - . - W - . - - . W . - . - . (3) W - . - . - . - - . - . - . W . . - . - W - . - - . - . - . - W . W . - . - . - - . - W - . - . . - . - . W . - - . W . - . - . (4) . W . - . - . - - . - W - . - . . - . - . W . - - . - . - . - W . - W - . - . - W . - . - . - . . - . - . - W - - . - . W . - . (5) . W . - . - . - - . - . W . - . . - . - . - W - W . - . - . - . . - W - . - . - - . - . - . - W . - . - . W . - - . - W - . - . (6) . W . - . - . - - . - . W . - . . - . - . - W - - . - W - . - . W - . - . - . - - . - . - . - W . - . - . W . - - . W . - . - . (7) . W . - . - . - - . - . - W - . W - . - . - . - - . - . - . W . . - . W . - . - - . - . - . - W . - W - . - . - - . - . W . - . (8) . W . - . - . - - . - . - W - . . - . - . - . W - . W . - . - . W - . - . - . - - . - W - . - . . - . - . - W - - . - . W . - . (9) . W . - . - . - - . - . - . W . . - W - . - . - - . - . - W - . . - . - . - . W - . - . W . - . W - . - . - . - - . - W - . - . (10) . W . - . - . - - . - . - . W . . - . - W - . - - . - . - . - W W - . - . - . - - . - W - . - . . - . - . W . - - . W . - . - . (11) . W . - . - . - - . - . - . - W . - . - . W . - W . - . - . - . . - W - . - . - - . - . W . - . . - . - . - W - - . - W - . - . (12) . - W - . - . - W . - . - . - . . - . - . - W - - . - . W . - . . - . - . - . W - W - . - . - . . - . W . - . - - . - . - W - . (13) . - W - . - . - - . - . W . - . . W . - . - . - - . - . - . - W W - . - . - . - - . - . - . W . . - . W . - . - - . - . - W - . (14) . - W - . - . - - . - . W . - . . W . - . - . - - . - . - . - W . - . - . W . - - . - W - . - . . - . - . - W - W . - . - . - . (15) . - W - . - . - - . - . W . - . . - . - . - W - W . - . - . - . . - . W . - . - - W - . - . - . . - . - . - . W - . - . - W - . (16) . - W - . - . - - . - . W . - . . - . - . - . W - . - W - . - . W - . - . - . - - . - . - . W . . W . - . - . - - . - . - W - . (17) . - W - . - . - - . - . - W - . . W . - . - . - - . - . W . - . . - . - . - . W W . - . - . - . . - . - . - W - - . - W - . - . (18) . - W - . - . - - . - . - W - . . W . - . - . - - . - . - . W . W - . - . - . - - . - W - . - . . - . - . - . W - . - . W . - . (19) . - W - . - . - - . - . - W - . . W . - . - . - - . - . - . W . . - . - W - . - W . - . - . - . . - . - . - . W - . - W - . - . (20) . - W - . - . - - . - . - W - . . - . W . - . - W . - . - . - . . - . - . - . W - . - . W . - . . - . - . - W - - W - . - . - . (21) . - W - . - . - - . - . - W - . . - . W . - . - - W - . - . - . . - . - . - . W - . - . W . - . . - . - . - W - W . - . - . - . (22) . - W - . - . - - . - . - W - . . - . - . - . W W . - . - . - . . - . W . - . - - . - . - . W . . - . - W - . - - W - . - . - . (23) . - W - . - . - - . - . - W - . . - . - . - . W W . - . - . - . . - . - W - . - - . - . - . W . . W . - . - . - - . - W - . - . (24) . - W - . - . - - . - . - W - . . - . - . - . W - W - . - . - . . - . W . - . - W . - . - . - . . - . - . - W - - . - . W . - . (25) . - W - . - . - - . - . - . W . . W . - . - . - - . - . - . - W . - . - W - . - W . - . - . - . . - . W . - . - - . - . - W - . (26) . - W - . - . - - . - . - . W . . W . - . - . - - . - . - . - W . - . - . W . - - . - W - . - . W - . - . - . - - . - . W . - . (27) . - W - . - . - - . - . - . - W . - . W . - . - - . - . - . W . W - . - . - . - - . - . - W - . . W . - . - . - - . - . W . - . (28) . - . W . - . - W . - . - . - . . - . - W - . - - . - . - . - W . W . - . - . - - . - . - . W . . - W - . - . - - . - . - W - . (29) . - . W . - . - W . - . - . - . . - . - W - . - - . - . - . - W . - . - . W . - - . W . - . - . . - . - . - W - - W - . - . - . (30) . - . W . - . - - W - . - . - . . - . - W - . - - . - . - . - W . - . - . W . - W . - . - . - . . - W - . - . - - . - . - . W . (31) . - . W . - . - - W - . - . - . . - . - . - W - - . W . - . - . . - . - . W . - - . - . - . - W W - . - . - . - - . - . W . - . (32) . - . W . - . - - W - . - . - . . - . - . - W - - . W . - . - . . - . - . W . - - . - . - . - W . - . - W - . - W . - . - . - . (33) . - . W . - . - - W - . - . - . . - . - . - W - - . - . W . - . W - . - . - . - - . - . - . - W . - . - . W . - - . W . - . - . (34) . - . W . - . - - W - . - . - . . - . - . - . W - . - . W . - . . - . - . - W - W . - . - . - . . - W - . - . - - . - . - W - . (35) . - . W . - . - - W - . - . - . . - . - . - . W - . - . - W - . W - . - . - . - - . W . - . - . . - . - W - . - - . - . - . W . (36) . - . W . - . - - . - . - W - . W - . - . - . - - . - . W . - . . W . - . - . - - . - . - . - W . - W - . - . - - . - . - . W . (37) . - . W . - . - - . - . - W - . . - . - . - . W - W - . - . - . . - . - . - W - W . - . - . - . . - W - . - . - - . - . W . - . (38) . - . W . - . - - . - . - W - . . - . - . - . W - . W . - . - . W - . - . - . - - . - . - . W . . - . - W - . - - W - . - . - . (39) . - . W . - . - - . - . - . W . W - . - . - . - - . - . - . - W . - . - W - . - - W - . - . - . . - . - . W . - - . W . - . - . (40) . - . W . - . - - . - . - . W . . - W - . - . - - . - . - . - W . W . - . - . - - . - . W . - . W - . - . - . - - . - . - W - . (41) . - . W . - . - - . - . - . W . . - . - W - . - - W - . - . - . . - . - . W . - W . - . - . - . . - W - . - . - - . - . - . - W (42) . - . W . - . - - . - . - . W . . - . - W - . - - . W . - . - . W - . - . - . - - . - . - W - . . - . - . - . W - W - . - . - . (43) . - . W . - . - - . - . - . - W W - . - . - . - - . W . - . - . . - . - . W . - - W - . - . - . . - . - . - W - - . - . W . - . (44) . - . W . - . - - . - . - . - W W - . - . - . - - . - . W . - . . - . - . - W - - W - . - . - . . - . - . W . - - . W . - . - . (45) . - . W . - . - - . - . - . - W . - . - W - . - - . W . - . - . W - . - . - . - - . - . - . W . . W . - . - . - - . - . - W - . (46) . - . - W - . - W . - . - . - . . - . W . - . - - . - . - W - . . - . - . - . W - W - . - . - . . - . - . - W - - . W . - . - . (47) . - . - W - . - W . - . - . - . . - . - . - . W - . - W - . - . . W . - . - . - - . - . - . W . . - W - . - . - - . - . - W - . (48) . - . - W - . - W . - . - . - . . - . - . - . W - . - . - W - . . - W - . - . - - . - . - . W . . W . - . - . - - . - W - . - . (49) . - . - W - . - - W - . - . - . . - . W . - . - - . - . - W - . . - . - . - . W - . W . - . - . W - . - . - . - - . - . - . W . (50) . - . - W - . - - W - . - . - . . - . W . - . - - . - . - . W . . - W - . - . - - . - . - . - W . - . - . W . - W . - . - . - . (51) . - . - W - . - - W - . - . - . . - . - . W . - W . - . - . - . . - . - . - W - - . - W - . - . . - . - . - . W - . W . - . - . (52) . - . - W - . - - W - . - . - . . - . - . - . W W . - . - . - . . - . W . - . - - . - . - . W . . - W - . - . - - . - . - W - . (53) . - . - W - . - - . W . - . - . W - . - . - . - - . - . - W - . . - . - . - . W - W - . - . - . . - . W . - . - - . - . - . W . (54) . - . - W - . - - . W . - . - . W - . - . - . - - . - . - . W . . W . - . - . - - . - . - . - W . - . - . W . - - . - W - . - . (55) . - . - W - . - - . W . - . - . . - . - . - . W - . - W - . - . . - . - . - W - W . - . - . - . . - . - . W . - - W - . - . - . (56) . - . - W - . - - . - . - . W . W - . - . - . - - . W . - . - . . - . - . - . W - . - . - W - . . - . W . - . - - W - . - . - . (57) . - . - W - . - - . - . - . W . W - . - . - . - - . - W - . - . . W . - . - . - - . - . - . - W . - . - . W . - - . W . - . - . (58) . - . - W - . - - . - . - . W . . W . - . - . - - . - W - . - . . - . - . - . W W . - . - . - . . - W - . - . - - . - . - W - . (59) . - . - W - . - - . - . - . W . . W . - . - . - - . - . - W - . . - W - . - . - W . - . - . - . . - . W . - . - - . - . - . - W (60) . - . - W - . - - . - . - . W . . W . - . - . - - . - . - W - . . - W - . - . - W . - . - . - . . - . - . - . W - . - W - . - . (61) . - . - W - . - - . - . - . W . . - . W . - . - W . - . - . - . . - W - . - . - - . - . - . - W . - . - . W . - - W - . - . - . (62) . - . - W - . - - . - . - . - W . - . W . - . - W . - . - . - . . - W - . - . - - . - . - W - . . W . - . - . - - . - . - . W . (63) . - . - W - . - - . - . - . - W . - . W . - . - W . - . - . - . . - . - . - W - - W - . - . - . . - . - . W . - - . W . - . - . (64) . - . - . W . - W . - . - . - . . - . - W - . - - W - . - . - . . - . - . - . W - . W . - . - . . - . - . - W - - . - W - . - . (65) . - . - . W . - - W - . - . - . . - . - . - W - W . - . - . - . . - W - . - . - - . - . W . - . . - . - . - . W - . - W - . - . (66) . - . - . W . - - W - . - . - . . - . - . - W - W . - . - . - . . - . W . - . - - . - . - . - W . - . - W - . - - . W . - . - . (67) . - . - . W . - - . W . - . - . W - . - . - . - - . - . - . W . . - . - W - . - - . - . - . - W . W . - . - . - - . - W - . - . (68) . - . - . W . - - . W . - . - . W - . - . - . - - . - . - . - W . - . W . - . - - W - . - . - . . - . - . - W - - . - . W . - . (69) . - . - . W . - - . W . - . - . W - . - . - . - - . - . - . - W . - . - W - . - - W - . - . - . . - . W . - . - - . - . - . W . (70) . - . - . W . - - . W . - . - . . - . - W - . - - . - . - . W . W - . - . - . - - . - W - . - . . W . - . - . - - . - . - . - W (71) . - . - . W . - - . W . - . - . . - . - W - . - - . - . - . - W W - . - . - . - - . - W - . - . . W . - . - . - - . - . - . W . (72) . - . - . W . - - . W . - . - . . - . - . - W - - W - . - . - . . - . W . - . - - . - . - . - W W - . - . - . - - . - . W . - . (73) . - . - . W . - - . W . - . - . . - . - . - W - - W - . - . - . . - . - . - . W - . - . W . - . W - . - . - . - - . - W - . - . (74) . - . - . W . - - . W . - . - . . - . - . - W - - . - W - . - . W - . - . - . - - . - . - . - W . W . - . - . - - . - . W . - . (75) . - . - . W . - - . - W - . - . W - . - . - . - - . - . W . - . . - . - . - . W - W - . - . - . . - . - . - W - - . W . - . - . (76) . - . - . W . - - . - W - . - . . W . - . - . - - . - . - . - W . - . - W - . - - . - . - . W . W - . - . - . - - . W . - . - . (77) . - . - . W . - - . - W - . - . . - . - . - W - W . - . - . - . . - W - . - . - - . - . W . - . . W . - . - . - - . - . - . - W (78) . - . - . W . - - . - W - . - . . - . - . - W - W . - . - . - . . - . - . - . W - W - . - . - . . - . - W - . - - . W . - . - . (79) . - . - . W . - - . - . - . - W . W . - . - . - - . - W - . - . W - . - . - . - - . - . - . W . . - . - W - . - - . W . - . - . (80) . - . - . - W - W . - . - . - . . - W - . - . - - . - . - . - W . - . - . W . - - . - W - . - . . W . - . - . - - . - . W . - . (81) . - . - . - W - - W - . - . - . . - . W . - . - W . - . - . - . . - . - . - . W - . - . W . - . . - W - . - . - - . - . - W - . (82) . - . - . - W - - W - . - . - . . - . - . W . - - . W . - . - . W - . - . - . - - . - W - . - . . - . - . - . W - . - . W . - . (83) . - . - . - W - - . W . - . - . W - . - . - . - - . - . - W - . . - . - . - . W - . - . W . - . . W . - . - . - - . - W - . - . (84) . - . - . - W - - . W . - . - . . - . - . - . W - W - . - . - . . - . - W - . - W . - . - . - . . - . - . W . - - . - W - . - . (85) . - . - . - W - - . - W - . - . . W . - . - . - - . - . W . - . . - . - . - . W W . - . - . - . . - W - . - . - - . - . - W - . (86) . - . - . - W - - . - W - . - . . W . - . - . - - . - . - . - W . - . - . W . - W . - . - . - . . - W - . - . - - . - . W . - . (87) . - . - . - W - - . - . W . - . . - W - . - . - W . - . - . - . . - . - . W . - - . - . - . - W . W . - . - . - - . - W - . - . (88) . - . - . - . W - W - . - . - . . - . W . - . - W . - . - . - . . - . - . - W - - . - . W . - . . - W - . - . - - . - . - W - . (89) . - . - . - . W - W - . - . - . . - . - W - . - - . W . - . - . W - . - . - . - - . - . - . W . . - . W . - . - - . - . - W - . (90) . - . - . - . W - . W . - . - . W - . - . - . - - . - . - W - . . W . - . - . - - . - . W . - . . - . - . - W - - . - W - . - . (91) . - . - . - . W - . - W - . - . W - . - . - . - - . W . - . - . . - . - . W . - - W - . - . - . . - . - . - W - - . - . W . - . (92) zoem-11-166/examples/power-of-2.azm0000644000402500021140000000142310040720541013710 00000000000000 \: zoem -i power-of-2 --allow=ls -s level=10 \: zoem -i power-of-2 --allow=ls -s level=11 \: This creates big files, by succesively doubling a string. \: It then writes the file characteristics to STDOUT, \: Use this to compute powers of two (you'll need to pipe it through \: tail and/or cut though). \formatted{ \if{\defined{key}{level}} {} {\def{level}{10}} \inform{Using\` `level=\level} \def{double#1}{ \switch{\level}{ {0}{} {1}{\1} { \setx{level}{\let{\level-1} } \write{stderr}{device}{[\level]}\double{\1\1} } } } } \double{* } \write{stderr}{device}{\@{\N}} \setx{cluefile}{\__fnout__} \writeto{-} \if{\cmp{ne}{\cluefile}{-}}{\@{\w}\system{ls}{{-l}{\cluefile}}\@{\W}}{} zoem-11-166/examples/power-of-2.ozm0000644000402500021140000000200010325261776013736 00000000000000* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * zoem-11-166/examples/catch.azm0000644000402500021140000000151110040711614013074 00000000000000 \: zoem -i catch -tl 3 \: (to see nested while structure back in output) \catch{towel}{ \apply{_#1\!{{\if{\cmp{eq}{\1}{d}}{Skipping the rest!\@{\N}\throw{towel}foo}{\1}\@{\N}}}}{ {a}{b}{c}{d}{e}{f} } } At the bottom 1 \@{\P} \catch{towel}{ \set{i}{0} \while{1}{ * i = \i BEFORE throw 1 \@{\I} \if{\eqt{eq}{\i}{2}}{\throw{towel}}{} \setx{i}{\let{\i+1}} \catch{towel}{ \set{j}{0} \while{1}{ before throw 2 \if{\eqt{eq}{\j}{3}}{\throw{towel}}{} \setx{j}{\let{\j+1}} i = \i and j = \j\@{\N} end of body 2 } } \: \if{\cmp{ne}{\__zoemstat__}{error}}{\__zoemput__}{} \@{\J} END of body 1 } } \@{\J} \: \if{\cmp{ne}{\__zoemstat__}{error}}{ \__zoemput__ }{} At the bottom again zoem-11-166/examples/catch.ozm0000644000402500021140000000071310325254476013133 00000000000000a b c Skipping the rest! At the bottom 1 * i = 0 BEFORE throw 1 before throw 2 i = 1 and j = 1 end of body 2 before throw 2 i = 1 and j = 2 end of body 2 before throw 2 i = 1 and j = 3 end of body 2 before throw 2 END of body 1 * i = 1 BEFORE throw 1 before throw 2 i = 2 and j = 1 end of body 2 before throw 2 i = 2 and j = 2 end of body 2 before throw 2 i = 2 and j = 3 end of body 2 before throw 2 END of body 1 * i = 2 BEFORE throw 1 At the bottom again zoem-11-166/examples/fib.azm0000644000402500021140000000066210373175740012575 00000000000000\: test with 'zoem -i fib -o -' \def{fib#1}{ \push{fibonacci} \set{a}{1} \set{b}{1} \set{c}{0} \while{\let{\a <= \1}}{ \setx{c}{\a} \setx{a}{\let{\a + \b}} \write{-}{txt}{\c\|} \setx{b}{\c} } \pop{fibonacci} } \: need to escape newlines below, lest they ruin the prompt \write{-}{device}{Enter a number please, then press , \@{\N>\s}}\ \setx{num}{\zinsert{-}}\ \fib{\num} zoem-11-166/examples/loop.azm0000644000402500021140000000372210016205024012765 00000000000000 \: It's possible to do repeated looping using apply. Using named macros \: it is not so bad. When using anonymous macros only it's kind of \: awkard due to how and when stuff is \: a) evaluated \: b) interpolated. \: A basic problem (with nested use of anonymous macros) is how to \: achieve use of the placeholders \1, \2 etc as local variables. Right \: now, this is done by using the feature that apply evaluates its first \: argument (the key/anon macro) before use. A second-level nested \: placeholder has to be written as \!1, and during this evaluation \: it will be rewritten to \1. It needs to be enclosed by other delay \: scopes (i.e. either \!!1 or \!{..\!1 ..}) because the first-level \: apply also evaluates its first argument (of which the nested apply is \: part). \: So, one zoem implementation challenge might be to create an alternative \: way of achieving this for which the syntax is less hideous. \: A related issue is e.g. how to recurse over grape data (currently \: not possible). \@{\P} nested application of apply using anonymous macros. \apply{_#1{[ \!apply{_#1{\!{ (\!let{\!1*\!1}) }}}{\1} ]\@{\N}}}{ {{1}{2}{3}{4}{5}} {{4}{5}{6}} {{7}{8}{9}} } \: First apply evaluates its first argument. \: \: _#1{[ \!apply{_#1{\!{ (\!let{\!1*\!1}) }}}{\1} ]\@{\N}} \: \: giving \: \: _#1{[ \apply{_#1{ (\!let{\!1*\!1}) }}{\1} ]\@{\N}} \: \: This anon key is then iterated, and first presented with {{1}{2}{3}{4}{5}}. \: So we get \: \: \apply{_#1{ (\!let{\!1*\!1}) }}{{1}{2}{3}{4}{5}} \: \: This apply evaluates its first argument, giving \: \: _#1{ (\let{\1*\1}) } \: \: and the rest is easy. \@{\P} nested application of apply using normal macros. \set{do1#1}{[ \apply{do2#1}{\1} ]\@{\N}} \set{do2#1}{ (\let{\1*\1}) } \apply{do1#1}{ {{1}{2}{3}{4}{5}} {{4}{5}{6}} {{7}{8}{9}} } \import{reverse.azm} \@{\P} reversing successive varargs \apply{_#1{\!reverse{\1}\@{\N}}}{ {{1}{2}{3}{4}{5}} {{4}{5}{6}} {{7}{8}{9}} } zoem-11-166/examples/loop.ozm0000644000402500021140000000045110325254476013021 00000000000000 nested application of apply using anonymous macros. [ (1) (4) (9) (16) (25) ] [ (16) (25) (36) ] [ (49) (64) (81) ] nested application of apply using normal macros. [ (1) (4) (9) (16) (25) ] [ (16) (25) (36) ] [ (49) (64) (81) ] reversing successive varargs {5}{4}{3}{2}{1} {6}{5}{4} {9}{8}{7} zoem-11-166/examples/meta.azm0000644000402500021140000000020210040722113012730 00000000000000\: not really shore whether lambda is appropriate. oh well. \def{lambda#2}{\setx{\1#1}{\2 says \!1}} \lambda{foo}{bar} \foo{moo} zoem-11-166/examples/meta.ozm0000644000402500021140000000001510325254477012773 00000000000000bar says moo zoem-11-166/examples/nest.azm0000644000402500021140000000051110372652074012776 00000000000000 \: Some more anon/nesting/delay arithmetic, not very exciting. \: See also loop.azm. \: Note that inspect#4 is a beta-stage primitive. \'set{data}{{a-b}{c-d}{e-f}} \'apply{ _#1{ \!{\'inspect{posix}{(.)-(.)}{_#2\!{{\2#\1\@{\N}}}}}{\1} } }{ \data } \'inspect{posix,vararg}{(.)-(.)}{_#2\!{{\2#\1\@{\N}}}}{\data} zoem-11-166/examples/nest.ozm0000644000402500021140000000003710372652427013021 00000000000000b#a d#c f#e {b#a }{d#c }{f#e } zoem-11-166/examples/reverse.azm0000644000402500021140000000047007675553350013515 00000000000000 \formatted{ \def{reverse#1}{ \push{user} \: being paranoid. \set{_a}{} \apply{_#1{\!setx{_a}{{\!1}\!_a}}}{\1} \: apply creates _#1{\setx{_a}{{\1}\_a}} \_a \pop{user} }} \set{list}{{1}{2}{3}{\!reverse{{a}{b}{c}}}{4}{5}{6}} before: \apply{protect#1}{{\list}} after : \reverse{\eval{\list}} zoem-11-166/examples/reverse.ozm0000644000402500021140000000012610325254477013523 00000000000000before: {1}{2}{3}{\reverse{{a}{b}{c}}}{4}{5}{6} after : {6}{5}{4}{{c}{b}{a}}{3}{2}{1} zoem-11-166/examples/scope.azm0000644000402500021140000000027707700253505013144 00000000000000 \set{level}{10} \setx{i}{0} \while{\let{\i<\level}}{ \defx{num}{\i} \setx{i}{\let{\i+1}} \push{user} } \while{\let{\i>0}}{ \pop{user} num is \num \setx{i}{\let{\i-1}} } zoem-11-166/examples/scope.ozm0000644000402500021140000000013210325254477013156 00000000000000num is 9 num is 8 num is 7 num is 6 num is 5 num is 4 num is 3 num is 2 num is 1 num is 0 zoem-11-166/examples/special.azm0000644000402500021140000000024610040732466013446 00000000000000\special{ {97}{b} {97}{c} {97}{d} } \@{\+{1}}a \@{\+{0}}a \@{\+{3}}a \@{\+{2}}a \@{\+{3}}a \@{\+{0}}a \@{\+{3}}a \@{\+{2}}a \@{\+{1}}a \@{\+{0}}a zoem-11-166/examples/special.ozm0000644000402500021140000000002410325254477013465 00000000000000b a d c d a d c b a zoem-11-166/examples/stress.azm0000644000402500021140000002133710720145730013352 00000000000000 \: This file checks whether various kinds of errors escalate correctly. \: It also checks for every primitive whether errors are pushed correctly \: so that catch can catch them. If a primitive has different error \: paths, all of them should be represented here. \: Process this file with \: zoem -i stress --system-honor --unsafe-silent --err-out -o - > stress.ozm . \: With valgrind, it should be memory and error clean. \: One should try to find cases where primitives (should) accept some kind \: of sublanguage, and test them with misfits. \: \begin{label}{{!}{a}} is/was a good example. \if{\defined{key}{get_it_on}}{}{ \write{-}{device}{Process this file with ../src/zoem -i stress --system-honor --unsafe-silent --err-out -s get_it_on=1 -o - > stress.ozm\@{\N} } \done } \set{defs}{\!{ \set{recurse_segment}{\recurse_segment} \set{recurse_stack}{\eval{\recurse_stack}} \set{overflow_user}{\push{user}\overflow_user} \set{underflow_user}{\pop{user}\underflow_user} \set{foo}{foo_start\@{ foo_at }foo_end} \set{__device__}{stress} \set{one}{1} \set{zero}{0} \set{abc}{abc} \set{def}{def} \set{ct}{0} \env{myenv}{myenv_start}{myenv_end} \env{myenv2}{myenv2_start}{myenv2_end} \begin{myenv} \begin{myenv2} }} \write{\__fnout__}{device}{DEFINITIONS USED:\apply{protect#1}{{\defs}}} \eval{\defs} \@{\P} \apply{_#2{ \!write{-}{device}{||| \1:\@{\N}} \!write{-}{device}{||| \!protect{\2}\@{\N}} \!catch{error}{\!abc[\2]\!def}\@{\P} \!setx{ct}{\!let{\!ct+1}} }}{ \!{ {undef in plain scope} {\nsk} {undef in at scope} {\@{\nsk}} {undef at deeper level} {\eval{\textmap{{word}{ucase}{number}{roman}}{\nsk}}} {undef in and scope} \: error at output time {\write{\__fnout__}{device}{\@{\&{\nsk}}}} {recurse segment} {\recurse_segment} {recurse stack} {\recurse_stack} {overflow user dictionary stack} {\overflow_user} {underflow user dictionary stack (requires nuser>nsegment)} {\underflow_user} {inserting spurious left curly} {\eval{\!""\__lc__}} {and scope in plain scope} {\&{\foo}} {at scope in and scope} {\@{\&{\foo}}} {incorrect anonymous key} {\_#1{\1}{bar}{foo}} {and scope in plain scope} {\&{\foo}} {incorrect anonymous key} {\_#1{\1}{bar}{foo}} \: xml sugar \: syntactig sugar happens at output time, not digest time. \: catch cannot catch this, write can. {some broken XML syntactic sugar} {\write{\__fnout__}{device}{\\\\}} {\@{\C}XML syntactic sugar underflow} {\write{\__fnout__}{device}{\\\<>\<>\<>}} {XML content syntax error} {\{\nsk}} \: \$#2 {error in $#2} {\${stress}{\nsk}} \: \%#1 \: grape keys \: !absence is not (yet) an error {absent grape node, fetched} {\%{nsg}} {absent grape node, freed} {\%free{nsg}} {absent grape node, dumped} {\%dump{nsg}} \: \apply#2 {no such key} {\apply{nsk#2}{{a}{b}}} {wrong anonymous key} {\apply{_#a{\1}}{{a}{b}}} {trailing arguments} {\apply{_#2{[\1\2]}}{{a}}} {argument does not parse} {\apply{_#2{[\1\2]}}{{a}{b}{c}{\nsk}}} \: \begin#2 {label does not exist} {\begin{nsl}} {argument does not parse} {\begin{myenv}{{\nsk}{\nsk}}} \: \branch#1 {parse error} {\branch{{\let{0<}}{}}} \: \catch#2 {uncaught catch} {\catch{towel}{\nsk}} {uncaught (delayed) error} {\catch{error}{\!{\nsk}}} {catch towel at 6} { \set{foo}{0} \catch{towel}{\while{\let{\foo<10}}{ foo \foo bar\@{\N} \if{\let{\foo==6}}{\throw{towel}}{} \setx{foo}{\let{\foo+1}} } } } \: \cmp#3 {argument does not parse} {\cmp{eq}{\nsk}{foo}} {no such mode} {\cmp{__}{bar}{foo}} \: \constant#1 {parse error (not fatal, trailing element)} {\constant{{(c)} boo {}}} \: \def#2 {wrong key signature} {\def{^zut}{foo}} \: \defined#2 {wrong mode} {\defined{__}{__}} \: \defx#2 {wrong key signature} {\defx{^zut}{foo}} {parse error} {\defx{zut}{\nsk}} \: \dofile#2 {no such file} {\dofile{no-such-file}{!+}} \: \dowhile#2 {parse error} {\dowhile{\nsk}{1}} {parse error} {\dowhile{1}{\nsk}} \: \end#1 {no such env} {\end{nse}} {cannot close myenv} {\end{myenv}} {can close myenv2} {\end{myenv2}} \: \env#3 {cannot define env while in environment} {\env{myenv3}{foo}{bar}} \: \eqt#3 {argument does not parse} {\eqt{eq}{\nsk}{1}} {no such mode} {\eqt{__}{1}{1}} {argument not numeric I} {\eqt{eq}{aap}{\one}} {argument not numeric II} {\eqt{eq}{aap}{\zero}} \: \eval#1 {parse error} {\eval{\nsk}} \: \f#2 {no such mode} {\f{nsm}{2.5}} {overflow I ?} {\f{sign}{111111111111111111111111111111}} {overflow II ?} {\f{sign}{3e100000}} {parse error} {\f{sign}{\nsk}} \: \finsert#1 {parse error} {\finsert{\nsk}} \: \format#1 \: todo: more format torturing. \: \formatted#2 \: hum, not very exciting. \: \fv#2 {no such mode} {\fv{nsm}{{1}{2}{3}}} {parse error} {\fv{sum}{{\zero}{\one}{\nsk}}} {this should work} {\fv{max}{{\zero}{\one}{2}}} \: \if#3 {parse error condition} {\if{\nsk}{}{}} {parse error if} {\if{1}{\nsk}{}} {parse error else} {\if{0}{}{\nsk}} \: \inspect#4 \: leave this until after inspect#4 rewrite. \: \f#3 {arithmetic exception in f} {\f{div}{1}{0}} \: let {syntax error in let} {\let{1+}} {another syntax error in let} {\let{1+sin(1,)}} {callback error in let} {\let{\nsk}} {nested callback error in let} {\let{\let{\nsk}}} {arithmetic exception in let} {\let{1/0}} {overflow in let} {\let{300**300}} {complicated and correct let expression, including redundant callbacks} {\let{\let{sin(\let{\one})}**2+\let{cos(\let{\one})}**2}} {complicated and failing let expression} {\let{\let{sin(\let{\one})}**2+\let{cos(\let{1/0})}**2}} \: \length#1 {parse error} {\length{\nsk}} \: \pop#1 \: under/overflow tested elsewhere. {no such dictionary stack} {\pop{nsds}} \: \protect#1 \: what could be problematic here ? \: \push#1 {no such dictionary stack} {\push{nsds}} \: \roman#1 {parse error} {\roman{\nsk}} {convert error} {\roman{abc}} \: \set#2 \: \setx#2 \: system {absent system call} {\system{#}} {failing system call} {\system{ls}{{-#}}} {finally a systemcall that should succeed} {\system{true}} {should close myenv} {\end{myenv}} \: \special#1 \: it'll mostly work. \: \switch#2 {parse error in pivot} {\switch{\nsk}{{}{}}} {parse error in clause} {\switch{foo}{{\nsk}{A}{b}{B}}} {parse error in case} {\switch{foo}{{foo}{\nsk}{b}{B}}} \: \table#5 \: not motivated; it is a sitting duck anyway. \: \tr#2 {this should work} {\tr{{from}{a-z}{to}{A-Z}{squash}{A-Z}}{squash the bookkeeper}} \: \trace#1 {parse error} {\trace{\nsk}} \: \try#1 \: todotodo \: \ucase#1 {parse error} {\textmap{{word}{ucase}}{\nsk}} \: \undef#1 {wrong signature} {\undef{!}} \: \vanish#1 {parse error} {\vanish{\nsk}} \: \while#2 {parse error condition} {\while{\nsk}{}} {parse error body} {\while{1}{\nsk}} \: \write#3 {open error} {\write{/no/such/file}{copy}{foo}} {no such filter} {\write{/dev/null}{nsf}{foo}} {parse error} {\write{/dev/null}{copy}{\nsk}} {throw} {\write{/dev/null}{copy}{\throw{towel}}} \: \writeto#1 \: {open error} \: {\writeto{/no/such/file}} \: \: this is in fact fatal, currently. too much stress. \: \zinsert#1 {inline file should work} {\zinsert{monkey}} {parse error} {\zinsert{\nsk}} {inline file with parse error} {\eval{\zinsert{fox}}} \: delay scope {delay parse error} {\write{\__fnout__}{device}{\!{\nsk}}} \: \: if not wrapped in write it is only seen by output, \: not by digest, so uncatchable. } } Done with \ct error tests. \={monkey}= \zero \one monkey see monkey do \== \={fox}= \zero \one \nsk \== zoem-11-166/examples/stress.reg0000644000402500021140000004246311573704177013360 00000000000000DEFINITIONS USED: \set{recurse_segment}{\recurse_segment} \set{recurse_stack}{\eval{\recurse_stack}} \set{overflow_user}{\push{user}\overflow_user} \set{underflow_user}{\pop{user}\underflow_user} \set{foo}{foo_start\@{ foo_at }foo_end} \set{__device__}{stress} \set{one}{1} \set{zero}{0} \set{abc}{abc} \set{def}{def} \set{ct}{0} \env{myenv}{myenv_start}{myenv_end} \env{myenv2}{myenv2_start}{myenv2_end} \begin{myenv} \begin{myenv2} myenv_start myenv2_start ||| undef in plain scope: ||| \nsk ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| undef in at scope: ||| \@{\nsk} abc[ sk]def ||| undef at deeper level: ||| \eval{\textmap{{word}{ucase}{number}{roman}}{\nsk}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| undef in and scope: ||| \write{\__fnout__}{device}{\@{\&{\nsk}}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <474> in ___ last key seen is ___ [filterAt] AND scope did not parse abc[]def ||| recurse segment: ||| \recurse_segment ___ [zoem] error around input line <474> in ___ last key seen is ___ [yamSegPush] exceeding maximum segment depth <200> abc[ ||| recurse stack: ||| \recurse_stack ___ [zoem] error around input line <474> in ___ last key seen is ___ [yamStackPush] exceeding maximum stack depth <100> abc[ ||| overflow user dictionary stack: ||| \overflow_user ___ [zoem] error around input line <474> in ___ last key seen is ___ [dictStackPush] no more than <100> dicts allowed in stack abc[ ||| underflow user dictionary stack (requires nuser>nsegment): ||| \underflow_user ___ [zoem] error around input line <474> in ___ last key seen is ___ [dictStackPop] cannot pop last scope! abc[ ||| inserting spurious left curly: ||| \eval{\!""\__lc__} ___ [zoem] error around input line <474> in ___ last key seen is <""> ___ [yamParseKey] no closing scope abc[ ||| and scope in plain scope: ||| \&{\foo} ___ [zoem] error around input line <474> in ___ last key seen is ___ [yamFindKey] illegal escape sequence <\&> abc ||| at scope in and scope: ||| \@{\&{\foo}} abc[foo_start___ [zoem] error around input line <474> in ___ last key seen is ___ [filterAt] unknown escape <@> { foo_at }foo_end]def ||| incorrect anonymous key: ||| \_#1{\1}{bar}{foo} ___ [zoem] error around input line <474> in ___ last key seen is <_> ___ [yamParseKey] found anon _#1{\1} with 2 arguments abc[ ||| and scope in plain scope: ||| \&{\foo} ___ [zoem] error around input line <474> in ___ last key seen is ___ [yamFindKey] illegal escape sequence <\&> abc ||| incorrect anonymous key: ||| \_#1{\1}{bar}{foo} ___ [zoem] error around input line <474> in ___ last key seen is <_> ___ [yamParseKey] found anon _#1{\1} with 2 arguments abc[ ||| some broken XML syntactic sugar: ||| \write{\__fnout__}{device}{\\\\} ___ [zoem] error around input line <474> in ___ last key seen is <<>#1> ___ [\<>#1] tag closes abc[ ||| XML syntactic sugar underflow: ||| \write{\__fnout__}{device}{\\\<>\<>\<>} ___ [zoem] error around input line <474> in ___ last key seen is <<>#1> ___ [\<>#1] XML syntactic sugar stack underflow at file <-> tag abc[ ||| XML content syntax error: ||| \{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| error in $#2: ||| \${stress}{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| absent grape node, fetched: ||| \%{nsg} ___ [zoem] error around input line <474> in ___ last key seen is <%#1> ___ [\%#1] no value associated with <{nsg}> abc[]def ||| absent grape node, freed: ||| \%free{nsg} ___ [zoem] error around input line <474> in ___ last key seen is <%free#1> ___ [\free#1] no value associated with <{nsg}> abc[]def ||| absent grape node, dumped: ||| \%dump{nsg} # printing node ___ [zoem] error around input line <474> in ___ last key seen is <%dump#1> ___ [\dump#1] no value associated with <{nsg}> abc[]def ||| no such key: ||| \apply{nsk#2}{{a}{b}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <474> in ___ last key seen is ___ [\apply#2] key does not expand abc[ ||| wrong anonymous key: ||| \apply{_#a{\1}}{{a}{b}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\apply#2] key part not ok abc[ ||| trailing arguments: ||| \apply{_#2{[\1\2]}}{{a}} ___ [\apply#2] (ignoring) trailing arguments abc[]def ||| argument does not parse: ||| \apply{_#2{[\1\2]}}{{a}{b}{c}{\nsk}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| label does not exist: ||| \begin{nsl} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\begin#2] env does not exist abc[ ||| argument does not parse: ||| \begin{myenv}{{\nsk}{\nsk}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <474> in ___ last key seen is ___ [\begin#2] arguments in env did not parse abc[ ||| parse error: ||| \branch{{\let{0<}}{}} ___ [getatom] unexpected token ___ [zoem] error around input line <474> in ___ last key seen is ___ [\let#1] expression did not parse abc[ ||| uncaught catch: ||| \catch{towel}{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| uncaught (delayed) error: ||| \catch{error}{\!{\nsk}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| catch towel at 6: ||| \set{foo}{0} \catch{towel}{\while{\let{\foo<10}}{ foo \foo bar\@{\N} \if{\let{\foo==6}}{\throw{towel}}{} \setx{foo}{\let{\foo+1}} } } abc[ foo 0 bar foo 1 bar foo 2 bar foo 3 bar foo 4 bar foo 5 bar foo 6 bar ]def ||| argument does not parse: ||| \cmp{eq}{\nsk}{foo} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| no such mode: ||| \cmp{__}{bar}{foo} ___ [cmp#3] unknown mode <__> abc[ ||| parse error (not fatal, trailing element): ||| \constant{{(c)} boo {}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\constant#1] spurious element abc[]def ||| wrong key signature: ||| \def{^zut}{foo} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\def#2] not a valid key signature: <^zut> abc[ ||| wrong mode: ||| \defined{__}{__} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\defined#2] invalid type <__> abc[ ||| wrong key signature: ||| \defx{^zut}{foo} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\defx#2] not a valid key signature: <^zut> abc[ ||| parse error: ||| \defx{zut}{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <474> in ___ last key seen is ___ [\defx#2] argument did not parse abc[ ||| no such file: ||| \dofile{no-such-file}{!+} ___ [\dofile#2] failed to open file abc[ ||| parse error: ||| \dowhile{\nsk}{1} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| parse error: ||| \dowhile{1}{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[1 ||| no such env: ||| \end{nse} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\end#2] env not found abc[ ||| cannot close myenv: ||| \end{myenv} abc[myenv_end]def ||| can close myenv2: ||| \end{myenv2} abc[myenv2_end]def ||| cannot define env while in environment: ||| \env{myenv3}{foo}{bar} abc[]def ||| argument does not parse: ||| \eqt{eq}{\nsk}{1} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| no such mode: ||| \eqt{__}{1}{1} ___ [eqt#3] unknown mode <__> abc[ ||| argument not numeric I: ||| \eqt{eq}{aap}{\one} abc[0]def ||| argument not numeric II: ||| \eqt{eq}{aap}{\zero} abc[1]def ||| parse error: ||| \eval{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| no such mode: ||| \f{nsm}{2.5} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\f#2] unknown mode abc[ ||| overflow I ?: ||| \f{sign}{111111111111111111111111111111} abc[1]def ||| overflow II ?: ||| \f{sign}{3e100000} abc[1]def ||| parse error: ||| \f{sign}{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| parse error: ||| \finsert{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| no such mode: ||| \fv{nsm}{{1}{2}{3}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\fv#2] unknown mode abc[ ||| parse error: ||| \fv{sum}{{\zero}{\one}{\nsk}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| this should work: ||| \fv{max}{{\zero}{\one}{2}} abc[2]def ||| parse error condition: ||| \if{\nsk}{}{} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <474> in ___ last key seen is ___ [\if#3] condition does not parse abc[ ||| parse error if: ||| \if{1}{\nsk}{} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| parse error else: ||| \if{0}{}{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| arithmetic exception in f: ||| \f{div}{1}{0} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\f#3] arithmetic exception for operator
abc[0]def ||| syntax error in let: ||| \let{1+} ___ [getatom] unexpected token ___ [zoem] error around input line <474> in ___ last key seen is ___ [\let#1] expression did not parse abc[ ||| another syntax error in let: ||| \let{1+sin(1,)} ___ [getatom] empty group not allowed ___ [zoem] error around input line <474> in ___ last key seen is ___ [\let#1] expression did not parse abc[ ||| callback error in let: ||| \let{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <474> in ___ last key seen is ___ [\let#1] arithmetic error occurred abc[ ||| nested callback error in let: ||| \let{\let{\nsk}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <474> in ___ last key seen is ___ [\let#1] arithmetic error occurred ___ [zoem] error around input line <474> in ___ last key seen is ___ [\let#1] arithmetic error occurred abc[ ||| arithmetic exception in let: ||| \let{1/0} ___ [flatten] arithmetic exception for op ___ [zoem] error around input line <474> in ___ last key seen is ___ [\let#1] arithmetic error occurred abc[ ||| overflow in let: ||| \let{300**300} abc[inf]def ||| complicated and correct let expression, including redundant callbacks: ||| \let{\let{sin(\let{\one})}**2+\let{cos(\let{\one})}**2} abc[1]def ||| complicated and failing let expression: ||| \let{\let{sin(\let{\one})}**2+\let{cos(\let{1/0})}**2} ___ [flatten] arithmetic exception for op ___ [zoem] error around input line <474> in ___ last key seen is ___ [\let#1] arithmetic error occurred ___ [zoem] error around input line <474> in ___ last key seen is ___ [\let#1] arithmetic error occurred ___ [zoem] error around input line <474> in ___ last key seen is ___ [\let#1] arithmetic error occurred abc[ ||| parse error: ||| \length{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| no such dictionary stack: ||| \pop{nsds} ___ [zoem] error around input line <474> in ___ last key seen is ___ [dictStackPop] cannot pop last scope! abc[ ||| no such dictionary stack: ||| \push{nsds} abc[]def ||| parse error: ||| \roman{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| convert error: ||| \roman{abc} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| absent system call: ||| \system{#} abc[ ||| failing system call: ||| \system{ls}{{-#}} abc[ ||| finally a systemcall that should succeed: ||| \system{true} abc[]def ||| should close myenv: ||| \end{myenv} abc[myenv_end]def ||| parse error in pivot: ||| \switch{\nsk}{{}{}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| parse error in clause: ||| \switch{foo}{{\nsk}{A}{b}{B}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| parse error in case: ||| \switch{foo}{{foo}{\nsk}{b}{B}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| this should work: ||| \tr{{from}{a-z}{to}{A-Z}{squash}{A-Z}}{squash the bookkeeper} abc[SQUASH THE BOKEPER]def ||| parse error: ||| \trace{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[] ||| parse error: ||| \textmap{{word}{ucase}}{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| wrong signature: ||| \undef{!} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\undef#1] key not defined in target scope abc[ ||| parse error: ||| \vanish{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| parse error condition: ||| \while{\nsk}{} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| parse error body: ||| \while{1}{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| open error: ||| \write{/no/such/file}{copy}{foo} ___ [zoem] error around input line <474> in ___ last key seen is ___ [yamOutputNew] can not open file for writing abc[ ||| no such filter: ||| \write{/dev/null}{nsf}{foo} ___ [zoem] error around input line <474> in ___ last key seen is ___ [\write#3] unknown filter abc[ ||| parse error: ||| \write{/dev/null}{copy}{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| throw: ||| \write{/dev/null}{copy}{\throw{towel}} abc[ ||| inline file should work: ||| \zinsert{monkey} abc[0 1 monkey see monkey do ]def ||| parse error: ||| \zinsert{\nsk} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[ ||| inline file with parse error: ||| \eval{\zinsert{fox}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [expand] no definition found for key abc[0 1 ||| delay parse error: ||| \write{\__fnout__}{device}{\!{\nsk}} ___ [zoem] error around input line <474> in ___ last key seen is ___ [filterDevice] ignoring escape <\n> \nskabc[]def Done with 96 error tests. ___ [zoem] error occurred ___ last key seen is ___ [dictStackFree] user dictionary not closed in output file <-> zoem-11-166/examples/stress2.azm0000644000402500021140000000470410656041021013427 00000000000000\if{\defined{key}{get_it_on}}{}{ \write{-}{device}{Process this file with ../src/zoem -i stress2 --system-honor --unsafe-silent --err-out -s get_it_on=1 -o - > stress2.ozm\@{\N} } \done } \set{__device__}{zut} \apply{_#2{\@{\P} @@@ \1 [\!protect{\2}] \@{\N} \!catch{error}{\2 ***} }}{\!{ {eval}{\eval{\!{\foo}}} {$#2}{\${zut}{\foo}} {<>#1}{\<\foo>} {<>#2}{\{\bar}} {<>#2}{\<\foo>{bar}} {alpha#1}{\alpha{\foo}} {apply#2}{\apply{}{}} {apply#2}{\apply{}{{\foo}}} {apply#2}{\appy{\foo#2}{}} {begin#2}{\begin{\foo}{}} {begin#2}{\begin{foo}{{\foo}{}}} {begin#2}{\begin{void}{{\foo}{}}} {begin#2}{\begin{void}{{foo}{\foo}}} {branch#1}{\branch{{\foo}{}}} {FALL THROUGH CLAUSE branch#1}{\branch{{}{\foo}}} {catch#2}{\catch{foo}{}} {catch#2}{\catch{error}{zut,bar,\foo,tim}} {catch#2}{\catch{error}{\eval{zut,bar,\foo,tim}}} {catch#2}{\catch{}{\foo}} {cmp#3}{\cmp{foo}{}{}} {cmp#3}{\cmp{eq}{\foo}{}} {def#2}{\def{&foo}{}} {defx#2}{\defx{foo}{\foo}} {defined#2}{\defined{foo}{}} {defined#2}{\defined{key}{\foo}} {defined#2}{\defined{key}{&foo}} {dofile#2}{\dofile{\foo}{!+}} {dofile#2}{\dofile{foo}{!}} {dowhile#2}{\dowhile{\foo}{0}} {FEATURE ?- note no stars dowhile#2}{\dowhile{0}{\foo}} {end#1}{\end{foo}} {end#1}{\end{\foo}} {eqt#3}{\eqt{foo}{}{}} {eqt#3}{\eqt{eq}{\foo}{}} {eval#1}{\eval{\foo}} {f#1}{\f{foo}} {f#1}{\f{\foo}} {finsert#1}{\finsert{\foo}} {format#2}{\format{foo}{{}}} {format#2}{\format{}{{\foo}}} {formatted#1}{\formatted{\foo}} {fv#2}{\fv{foo}{{}}} {fv#2}{\fv{sum}{{\foo}}} {if#3}{\if{\foo}{}{}} {if#3}{\if{1}{\foo}{}} {inspect#4}{\inspect{}{}{}{}} {length#1}{\length{\foo}} {let#1}{\let{\foo}} {pop#1}{\pop{foo}} {pop#1}{\pop{\foo}} {push#1}{\push{\foo}} {ref#2}{\ref{foo}{n}} {ref#2}{\ref{misc}{\foo}} {ALWAYS WORKS refload#5}{\refload{\foo&!}{}{}{}{}{}} {roman#1}{\roman{\foo}} {NO CHECKS YET ON KEYS special#1}{\special{{foo}{}}} {special#1}{\special{10}{{\foo}}} {switch#2}{\switch{\foo}{{}{}}} {switch#2}{\switch{foo}{{\foo}{}}} {ERROR MSGS GO INTO LOST PIPE system#3}{\system{ls}{{-!}}} {table#5}{\table{\foo}{\foo}{\foo}{\foo}{\foo}} {throw#2}{\throw{foo}{}} {throw#2}{\throw{error}{\foo ka-ching}} {tr#4}{\tr{}{}{}{\foo}} {tr#4}{\tr{\foo}} {OF COURSE try#1}{\try{\foo}} {ucase#1}{\ucase{\foo}} {undef#1}{\undef{foof}} {undef#1}{\undef{\foo}} {vanish#1}{\vanish{\foo}} {while#2}{\while{\foo}{}} {while#2}{\while{1}{\foo}} {write#3}{\write{\foo}{}{}} {write#3}{\write{/etc/foobar}{}{}} {write#3}{\write{/dev/null}{copy}{\foo}} {writeto#1}{\writeto{\foo}} }} zoem-11-166/examples/stress2.reg0000644000402500021140000002747611573704374013450 00000000000000 @@@ eval [\eval{\!{\foo}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ $#2 [\${zut}{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ <>#1 [\<\foo>] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ <>#2 [\{\bar}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ <>#2 [\<\foo>{bar}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ alpha#1 [\alpha{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ apply#2 [\apply{}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\apply#2] key part not ok @@@ apply#2 [\apply{}{{\foo}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ apply#2 [\appy{\foo#2}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ begin#2 [\begin{\foo}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\begin#2] env <\foo> does not exist @@@ begin#2 [\begin{foo}{{\foo}{}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\begin#2] env does not exist @@@ begin#2 [\begin{void}{{\foo}{}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\begin#2] env does not exist @@@ begin#2 [\begin{void}{{foo}{\foo}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\begin#2] env does not exist @@@ branch#1 [\branch{{\foo}{}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ FALL THROUGH CLAUSE branch#1 [\branch{{}{\foo}}] *** @@@ catch#2 [\catch{foo}{}] ___ [\catch#2] cannot catch @@@ catch#2 [\catch{error}{zut,bar,\foo,tim}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key zut,bar, *** @@@ catch#2 [\catch{error}{\eval{zut,bar,\foo,tim}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key zut,bar, *** @@@ catch#2 [\catch{}{\foo}] ___ [\catch#2] cannot catch <> @@@ cmp#3 [\cmp{foo}{}{}] ___ [cmp#3] unknown mode @@@ cmp#3 [\cmp{eq}{\foo}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ def#2 [\def{&foo}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\def#2] not a valid key signature: <&foo> @@@ defx#2 [\defx{foo}{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <88> in ___ last key seen is ___ [\defx#2] argument did not parse @@@ defined#2 [\defined{foo}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\defined#2] invalid type @@@ defined#2 [\defined{key}{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <88> in ___ last key seen is ___ [\defined#2] access string does not eval @@@ defined#2 [\defined{key}{&foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\defined#2] argument is not a valid key signature @@@ dofile#2 [\dofile{\foo}{!+}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ dofile#2 [\dofile{foo}{!}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\dofile#2] Second arg not in {!?}x{+-} @@@ dowhile#2 [\dowhile{\foo}{0}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ FEATURE ?- note no stars dowhile#2 [\dowhile{0}{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key 0 @@@ end#1 [\end{foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\end#2] env not found @@@ end#1 [\end{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\end#2] env <\foo> not found @@@ eqt#3 [\eqt{foo}{}{}] ___ [eqt#3] unknown mode @@@ eqt#3 [\eqt{eq}{\foo}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ eval#1 [\eval{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ f#1 [\f{foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ f#1 [\f{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ finsert#1 [\finsert{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ format#2 [\format{foo}{{}}] foo *** @@@ format#2 [\format{}{{\foo}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ formatted#1 [\formatted{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ fv#2 [\fv{foo}{{}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\fv#2] unknown mode @@@ fv#2 [\fv{sum}{{\foo}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ if#3 [\if{\foo}{}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <88> in ___ last key seen is ___ [\if#3] condition does not parse @@@ if#3 [\if{1}{\foo}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ inspect#4 [\inspect{}{}{}{}] *** @@@ length#1 [\length{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ let#1 [\let{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <88> in ___ last key seen is ___ [\let#1] arithmetic error occurred @@@ pop#1 [\pop{foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [dictStackPop] cannot pop last scope! @@@ pop#1 [\pop{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [dictStackPop] cannot pop last scope! @@@ push#1 [\push{\foo}] *** @@@ ref#2 [\ref{foo}{n}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ ref#2 [\ref{misc}{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ ALWAYS WORKS refload#5 [\refload{\foo&!}{}{}{}{}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ roman#1 [\roman{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ NO CHECKS YET ON KEYS special#1 [\special{{foo}{}}] *** @@@ special#1 [\special{10}{{\foo}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ switch#2 [\switch{\foo}{{}{}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ switch#2 [\switch{foo}{{\foo}{}}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ ERROR MSGS GO INTO LOST PIPE system#3 [\system{ls}{{-!}}] @@@ table#5 [\table{\foo}{\foo}{\foo}{\foo}{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ throw#2 [\throw{foo}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [throw#2] is unthrowable, throwing error instead @@@ throw#2 [\throw{error}{\foo ka-ching}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error around input line <88> in ___ last key seen is ___ [error :: ] @@@ tr#4 [\tr{}{}{}{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ tr#4 [\tr{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ OF COURSE try#1 [\try{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key *** @@@ ucase#1 [\ucase{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ undef#1 [\undef{foof}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\undef#1] key not defined in target scope @@@ undef#1 [\undef{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\undef#1] not a valid key signature: <\foo> @@@ vanish#1 [\vanish{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ while#2 [\while{\foo}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ while#2 [\while{1}{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ write#3 [\write{\foo}{}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\write#3] unknown filter <> @@@ write#3 [\write{/etc/foobar}{}{}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [\write#3] unknown filter <> @@@ write#3 [\write{/dev/null}{copy}{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key @@@ writeto#1 [\writeto{\foo}] ___ [zoem] error around input line <88> in ___ last key seen is ___ [expand] no definition found for key ___ [zoem] error occurred ___ last key seen is ___ [dictStackFree] user dictionary <\foo> not closed in output file <-> zoem-11-166/examples/tr.azm0000644000402500021140000000107610325245217012454 00000000000000\tr{{from}{abcd-g}{delete}{hij}{to}{1234-7}}{abcdefghijlmn} \tr{{from}{d-gI}{to}{4-7i}{delete}{hij}}{map D-G and remove HIJ altogether, is what I say} \tr{{delete}{hij}}{defghijklm} \tr{{squash}{^}{from}{^a-zA-Z.}{to}{[* *]}}{ *!* abolish *!* capital *!* punishment} \tr{{from}{[:lower:]}{to}{[:upper:]}}{\tr{{squash}{^}{from}{^a-zA-Z.}{to}{[* *]}}{ *!* abolish *!* capital *!* punishment}} \tr{{from}{^a-zA-Z.}{to}{[*_*]}}{ complement with neither squash nor delete } \tr{{squash}{[:alpha:]}}{squash the bookkeeper} \tr{{squash}{[:alpha:]}}{squash the bookkeeper} zoem-11-166/examples/tr.ozm0000644000402500021140000000031510325254477012475 000000000000001234567lmn map D-G an4 r5mov5 HJ alto75t5r, s wat say defgklm abolish capital punishment ABOLISH CAPITAL PUNISHMENT __complement__with__neither__squash__nor__delete__ squash the bokeper squash the bokeper zoem-11-166/examples/txt-table.azm0000644000402500021140000000747110723010311013723 00000000000000 \: Primitive txt-table formatting; no line wraps possible yet. \: \: This is dense stuff. It can be made more legible by exercising \formatted#1. \: The formatted result looks better. \: The first example inputs look quite horrid, because they use apply as well. \: The main thing of the goo below is that formatting and content have \: been largely/completely separated. Note that we must specify \@{\w} \: or zoem will gobble up the carefully prepared white-space formatting. \set{lrule}{.--------------------.--------------------.--------------------.} \set{rule}{^--------------------^--------------------^--------------------^} \@{\w}\lrule \apply{_#3{\!{\format{|%{{align}{center}{padding}{{()}}{delimit}{'}{width}{20}}| %{{align}{left}{width}{18}}|%{{align}{right}{width}{18}} |}{{(\1)}{[\2]}{\3}}} \rule }}{ {aap} {noot} {mies} {snoep} {bal} {vork} {tafel} {boom} {ma} } \@{\W\P} \@{\w}\apply{_#2{\!{\format{ |%{ {align}{right} {width}{6} } %{ {align}{right} {padding}{{.}} {delimit}{{ }} {width}{30} }}{ {\1}{\2}} }}}{ {1}{The first line} {2}{The second line} {3}{boo} } \@{\W\P} \@{\w}\apply{_#1{\!{\format{%{{align}{center}{padding}{{.-'''-}}{delimit}{ }{width}{60}}.}{{\1}}} }}{ {The first line}{The second line}{boo}} \@{\W\P} \: \@{\w}\apply{_#1{\!{\format{%{{align}{center}{padding}{{-}}{delimit}{'}{alignat}{{.}{10}}{width}{20}}}{{\1}}} }}{ {12.1239} {234.23} {0.33} {.0004} {103482390483029.23094830} {foo} } \@{\W\P} \set{width}{50} \set{offset}{26} \@{\w}\apply{_#2{\!{\format{%{{align}{center}{padding}{{-+H+}}{delimit}{ }{alignat}{{^_^}{\offset}}{width}{\width}}\""-}{{\1 ^_^ \2}}} }}{ {big_tree}{small_mouse}{long_road}{short_visit}{warm_sun}{cold_beer}{free_speech}{stay_put} } \@{\W\P} \set{circumstances}{ {There has grown up in the minds of certain groups} {in this country the notion that because a man or corporation} {has made a profit out of the public for a number of years,} {the government and the courts are charged with the duty} {of guaranteeing such profit in the future, even} {in the face of changing circumstances and contrary to public interest.} {This strange doctrine is not supported by statute or common law.} {Neither individuals nor corporations have any right} {to come into court} {and ask that the clock of history be stopped, or turned back.} } \@{\w} \format{%{ {align}{center} {padding}{{'}} {delimit}{{) }{ (}} {width}{80} {reuse}{*} {border}{{[ }{ ]\@{\n}}} }}{ \circumstances } \@{\W\P} \@{\w} \format{%{ {length}{{length}} {align}{center} {padding}{{\\ /}} {delimit}{{) }{ (}} {width}{80} {reuse}{*} {border}{{[ }{ ]\@{\n}}} }}{ \circumstances } \@{\W\P} \def{mylength#2}{\length{\1}} \@{\w} \format{%{ {align}{left} {padding}{{\\ /}} {delimit}{{) }{ (}} {length}{{mylength}{boo}} {width}{80} {reuse}{*} {border}{{[ }{ ]\@{\n}}} }}{ \circumstances } \@{\W\P} \@{\w} \format{%{ {align}{right} {padding}{{\\ /}} {delimit}{{) }{ (}} {width}{80} {reuse}{*} {border}{{[ }{ ]\@{\n}}} }}{ {There has grown up in the minds of certain groups} {in this country the notion that because a man or corporation} {has made a profit out of the public for a number of years,} {the government and the courts are charged with the duty} {of guaranteeing such profit in the future, even} {in the face of changing circumstances and contrary to public interest.} {This strange doctrine is not supported by statute or common law.} {Neither individuals nor corporations have any right} {to come into court} {and ask that the clock of history be stopped, or turned back.} } \@{\W\P} \format{%{{align}{right}{width}{10}{reuse}{*}{padding}{'}}}{ {beauty}{lies}{in}{the}{eye}{of}{the}{beholder} } \textmap{{repeat}{8}}{1234567890} zoem-11-166/examples/txt-table.ozm0000644000402500021140000001110410723020465013740 00000000000000.--------------------.--------------------.--------------------. |()()()('(aap)'()()()| [noot] | mies | ^--------------------^--------------------^--------------------^ |()()()'(snoep)')()()| [bal] | vork | ^--------------------^--------------------^--------------------^ |()()()'(tafel)')()()| [boom] | ma | ^--------------------^--------------------^--------------------^ | 1 ........{ }The first line{ } | 2 .......{ }The second line{ } | 3 ...................{ }boo{ } .-'''-.-'''-.-'''-.-'''The first line-'''-.-'''-.-'''-.-'''-. .-'''-.-'''-.-'''-.-'''The second line'''-.-'''-.-'''-.-'''-. .-'''-.-'''-.-'''-.-'''-.-'''boo'''-.-'''-.-'''-.-'''-.-'''-. ------'12.1239'----- -----'234.23'------- -------'0.33'------- --------'.0004'----- '103482390483029.23094830' ------'foo'--------- -+H+-+H+-+H+-+big_tree ^_^ small_mouse-+H+-+H+-+H+- -+H+-+H+-+H+-long_road ^_^ short_visit-+H+-+H+-+H+- -+H+-+H+-+H+-+warm_sun ^_^ cold_beerH+-+H+-+H+-+H+- -+H+-+H+-+Hfree_speech ^_^ stay_put+H+-+H+-+H+-+H+- [ ''''''''''''') There has grown up in the minds of certain groups ('''''''''''' ] [ ''''''') in this country the notion that because a man or corporation (''''''' ] [ '''''''') has made a profit out of the public for a number of years, ('''''''' ] [ '''''''''') the government and the courts are charged with the duty (''''''''' ] [ '''''''''''''') of guaranteeing such profit in the future, even (''''''''''''' ] [ '') in the face of changing circumstances and contrary to public interest. ('' ] [ ''''') This strange doctrine is not supported by statute or common law. (''''' ] [ '''''''''''') Neither individuals nor corporations have any right (''''''''''' ] [ '''''''''''''''''''''''''''') to come into court ('''''''''''''''''''''''''''' ] [ ''''''') and ask that the clock of history be stopped, or turned back. ('''''' ] [ \ /\ /\ /\) There has grown up in the minds of certain groups (\ /\ /\ / ] [ \ /\ ) in this country the notion that because a man or corporation ( /\ / ] [ \ /\ /) has made a profit out of the public for a number of years, (\ /\ / ] [ \ /\ /\ ) the government and the courts are charged with the duty (/\ /\ / ] [ \ /\ /\ /\ ) of guaranteeing such profit in the future, even (/\ /\ /\ / ] [ \ ) in the face of changing circumstances and contrary to public interest. ( / ] [ \ /\) This strange doctrine is not supported by statute or common law. (/\ / ] [ \ /\ /\ /) Neither individuals nor corporations have any right ( /\ /\ / ] [ \ /\ /\ /\ /\ /\ /\ /) to come into court (\ /\ /\ /\ /\ /\ /\ / ] [ \ /\ ) and ask that the clock of history be stopped, or turned back. ( /\ / ] [ ) There has grown up in the minds of certain groups (/\ /\ /\ /\ /\ /\ / ] [ ) in this country the notion that because a man or corporation ( /\ /\ /\ / ] [ ) has made a profit out of the public for a number of years, (\ /\ /\ /\ / ] [ ) the government and the courts are charged with the duty ( /\ /\ /\ /\ / ] [ ) of guaranteeing such profit in the future, even ( /\ /\ /\ /\ /\ /\ / ] [ ) in the face of changing circumstances and contrary to public interest. (\ / ] [ ) This strange doctrine is not supported by statute or common law. ( /\ /\ / ] [ ) Neither individuals nor corporations have any right ( /\ /\ /\ /\ /\ / ] [ ) to come into court (\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ / ] [ ) and ask that the clock of history be stopped, or turned back. (/\ /\ /\ / ] [ \ /\ /\ /\ /\ /\ /\) There has grown up in the minds of certain groups ( ] [ \ /\ /\ /\ ) in this country the notion that because a man or corporation ( ] [ \ /\ /\ /\ /) has made a profit out of the public for a number of years, ( ] [ \ /\ /\ /\ /\ ) the government and the courts are charged with the duty ( ] [ \ /\ /\ /\ /\ /\ /\ ) of guaranteeing such profit in the future, even ( ] [ \ /) in the face of changing circumstances and contrary to public interest. ( ] [ \ /\ /\ ) This strange doctrine is not supported by statute or common law. ( ] [ \ /\ /\ /\ /\ /\ ) Neither individuals nor corporations have any right ( ] [ \ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /) to come into court ( ] [ \ /\ /\ /\) and ask that the clock of history be stopped, or turned back. ( ] ''''beauty''''''lies''''''''in'''''''the'''''''eye''''''''of'''''''the''beholder 12345678901234567890123456789012345678901234567890123456789012345678901234567890 zoem-11-166/examples/xml.azm0000644000402500021140000000036107557217526012642 00000000000000 \set{opts}{a=b c=d} \setx{tmp}{\\\} \ asdlfj daklfj adskfjladj dsfjaldsfjkl \> the quick brown etc \{hum ha ho} \ the quick brown etc \ bleech \> \ \> zoem-11-166/examples/xml.ozm0000644000402500021140000000032210325254477012646 00000000000000 asdlfj daklfj adskfjladj dsfjaldsfjkl the quick brown etc hum ha ho the quick brown etc bleech