lnav-0.7.0/000775 000765 000024 00000000000 12315725123 012731 5ustar00stackstaff000000 000000 lnav-0.7.0/aclocal.m4000664 000765 000024 00000143331 12313323141 014566 0ustar00stackstaff000000 000000 # generated automatically by aclocal 1.14 -*- Autoconf -*- # Copyright (C) 1996-2013 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_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. 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-2013 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.14' 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.14], [], [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.14])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-2013 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-2013 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_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$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-2013 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. # 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", "OBJC", "OBJCXX", "UPC", or "GJC". # 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 m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" 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". rm -rf conftest.dir 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 10 /bin/sh. echo '/* dummy */' > 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 ;; msvc7 | msvc7msys | 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], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2013 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_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf 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"` # 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'`; 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-2013 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 macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # 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.65])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], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) 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], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [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([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # 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])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro 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 # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi]) 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-2013 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-2013 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. # 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])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2013 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_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-2013 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_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 is modern enough. # If it is, 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 --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2013 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_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])]) # Copyright (C) 1999-2013 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_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 1999-2013 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_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). m4_define_default([_AM_PYTHON_INTERPRETER_LIST], [python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version is >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Python interpreter is too old])]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Getting [:3] seems to be dnl the best way to do this; it's what "site.py" does in the standard dnl library. AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made dnl distinct variables so they can be overridden if need be. However, dnl general consensus is that you shouldn't need this ability. AC_SUBST([PYTHON_PREFIX], ['${prefix}']) AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) dnl At times (like when building shared libraries) you may want dnl to know which OS platform Python thinks this is. AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': can_use_sysconfig = 0 except ImportError: pass" dnl Set up 4 directories: dnl pythondir -- where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON script directory], [am_cv_python_pythondir], [if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl pkgpythondir -- $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl pyexecdir -- directory for installing python extension modules dnl (shared libraries) dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], [am_cv_python_pyexecdir], [if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) # Copyright (C) 2001-2013 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_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2013 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_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # 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 ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file 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 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 if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done 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]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2013 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_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2013 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-2013 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_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-2013 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_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. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} 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([ax_sqlite3.m4]) m4_include([ax_with_curses.m4]) m4_include([lnav.m4]) lnav-0.7.0/AUTHORS000664 000765 000024 00000000303 12302755320 013773 0ustar00stackstaff000000 000000 Primary Author -------------- Timothy Stack (timothyshanestack@gmail.com) Contributors ------------ Suresh Sundriyal (sureshsundriyal@gmail.com) Matt Dordal (matt@dordal.org) Henrietta Stack lnav-0.7.0/ax_sqlite3.m4000664 000765 000024 00000011574 12231751021 015250 0ustar00stackstaff000000 000000 dnl $Id: ax_sqlite3.m4,v 1.2 2006/08/30 14:28:55 mloskot Exp $ dnl dnl @synopsis AX_LIB_SQLITE3([MINIMUM-VERSION]) dnl dnl Test for the SQLite 3 library of a particular version (or newer) dnl dnl This macro takes only one optional argument, required version dnl of SQLite 3 library. If required version is not passed, dnl 3.0.0 is used in the test of existance of SQLite 3. dnl dnl If no intallation prefix to the installed SQLite library is given dnl the macro searches under /usr, /usr/local, and /opt. dnl dnl This macro calls: dnl dnl AC_SUBST(SQLITE3_CFLAGS) dnl AC_SUBST(SQLITE3_LDFLAGS) dnl AC_SUBST(SQLITE3_LIBS) dnl AC_SUBST(SQLITE3_VERSION) dnl dnl And sets: dnl dnl HAVE_SQLITE3 dnl dnl @category InstalledPackages dnl @category Cxx dnl @author Mateusz Loskot dnl @version $Date: 2006/08/30 14:28:55 $ dnl @license AllPermissive dnl dnl $Id: ax_sqlite3.m4,v 1.2 2006/08/30 14:28:55 mloskot Exp $ dnl AC_DEFUN([AX_LIB_SQLITE3], [ AC_ARG_WITH([sqlite3], AC_HELP_STRING( [--with-sqlite3=@<:@ARG@:>@], [use SQLite 3 library @<:@default=yes@:>@, optionally specify the prefix for sqlite3 library] ), [ if test "$withval" = "no"; then WANT_SQLITE3="no" elif test "$withval" = "yes"; then WANT_SQLITE3="yes" ac_sqlite3_path="" else WANT_SQLITE3="yes" ac_sqlite3_path="$withval" fi ], [WANT_SQLITE3="yes"] ) SQLITE3_CFLAGS="" SQLITE3_LDFLAGS="" SQLITE3_LIBS="" SQLITE3_VERSION="" if test "x$WANT_SQLITE3" = "xyes"; then ac_sqlite3_header="sqlite3.h" sqlite3_version_req=ifelse([$1], [], [3.0.0], [$1]) sqlite3_version_req_shorten=`expr $sqlite3_version_req : '\([[0-9]]*\.[[0-9]]*\)'` sqlite3_version_req_major=`expr $sqlite3_version_req : '\([[0-9]]*\)'` sqlite3_version_req_minor=`expr $sqlite3_version_req : '[[0-9]]*\.\([[0-9]]*\)'` sqlite3_version_req_micro=`expr $sqlite3_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` if test "x$sqlite3_version_req_micro" = "x" ; then sqlite3_version_req_micro="0" fi sqlite3_version_req_number=`expr $sqlite3_version_req_major \* 1000000 \ \+ $sqlite3_version_req_minor \* 1000 \ \+ $sqlite3_version_req_micro` AC_MSG_CHECKING([for SQLite3 library >= $sqlite3_version_req]) if test "$ac_sqlite3_path" != ""; then ac_sqlite3_ldflags="-L$ac_sqlite3_path/lib" ac_sqlite3_cppflags="-I$ac_sqlite3_path/include" else for ac_sqlite3_path_tmp in /usr /usr/local /opt ; do if test -f "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header" \ && test -r "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header"; then ac_sqlite3_path=$ac_sqlite3_path_tmp ac_sqlite3_cppflags="-I$ac_sqlite3_path_tmp/include" ac_sqlite3_ldflags="-L$ac_sqlite3_path_tmp/lib" break; fi done fi ac_sqlite3_ldflags="$ac_sqlite3_ldflags" ac_sqlite3_libs="-lsqlite3" saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $ac_sqlite3_cppflags" AC_LANG_PUSH(C++) AC_COMPILE_IFELSE( [ AC_LANG_PROGRAM([[@%:@include ]], [[ #if (SQLITE_VERSION_NUMBER >= $sqlite3_version_req_number) // Everything is okay #else # error SQLite version is too old #endif ]] ) ], [ AC_MSG_RESULT([yes]) success="yes" ], [ AC_MSG_RESULT([not found]) succees="no" ] ) AC_LANG_POP([C++]) CPPFLAGS="$saved_CPPFLAGS" if test "$success" = "yes"; then SQLITE3_CFLAGS="$ac_sqlite3_cppflags" SQLITE3_LDFLAGS="$ac_sqlite3_ldflags" SQLITE3_LIBS="$ac_sqlite3_libs" ac_sqlite3_header_path="$ac_sqlite3_path/include/$ac_sqlite3_header" dnl Retrieve SQLite release version if test "x$ac_sqlite3_header_path" != "x"; then ac_sqlite3_version=`cat $ac_sqlite3_header_path \ | grep '#define.*SQLITE_VERSION.*\"' | sed -e 's/.* "//' \ | sed -e 's/"//'` if test $ac_sqlite3_version != ""; then SQLITE3_VERSION=$ac_sqlite3_version else AC_MSG_WARN([Can not find SQLITE_VERSION macro in sqlite3.h header to retrieve SQLite version!]) fi fi AC_DEFINE([HAVE_SQLITE3], [], [sqlite3]) fi fi AC_SUBST(SQLITE3_CFLAGS) AC_SUBST(SQLITE3_LDFLAGS) AC_SUBST(SQLITE3_LIBS) AC_SUBST(SQLITE3_VERSION) ]) lnav-0.7.0/ax_with_curses.m4000664 000765 000024 00000060733 12211635053 016230 0ustar00stackstaff000000 000000 # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_with_curses.html # =========================================================================== # # SYNOPSIS # # AX_WITH_CURSES # # DESCRIPTION # # This macro checks whether a SysV or X/Open-compatible Curses library is # present, along with the associated header file. The NcursesW # (wide-character) library is searched for first, followed by Ncurses, # then the system-default plain Curses. The first library found is the # one returned. # # The following options are understood: --with-ncursesw, --with-ncurses, # --without-ncursesw, --without-ncurses. The "--with" options force the # macro to use that particular library, terminating with an error if not # found. The "--without" options simply skip the check for that library. # The effect on the search pattern is: # # (no options) - NcursesW, Ncurses, Curses # --with-ncurses --with-ncursesw - NcursesW only [*] # --without-ncurses --with-ncursesw - NcursesW only [*] # --with-ncursesw - NcursesW only [*] # --with-ncurses --without-ncursesw - Ncurses only [*] # --with-ncurses - NcursesW, Ncurses [**] # --without-ncurses --without-ncursesw - Curses only # --without-ncursesw - Ncurses, Curses # --without-ncurses - NcursesW, Curses # # [*] If the library is not found, abort the configure script. # # [**] If the second library (Ncurses) is not found, abort configure. # # The following preprocessor symbols may be defined by this macro if the # appropriate conditions are met: # # HAVE_CURSES - if any SysV or X/Open Curses library found # HAVE_CURSES_ENHANCED - if library supports X/Open Enhanced functions # HAVE_CURSES_COLOR - if library supports color (enhanced functions) # HAVE_CURSES_OBSOLETE - if library supports certain obsolete features # HAVE_NCURSESW - if NcursesW (wide char) library is to be used # HAVE_NCURSES - if the Ncurses library is to be used # # HAVE_CURSES_H - if is present and should be used # HAVE_NCURSESW_H - if should be used # HAVE_NCURSES_H - if should be used # HAVE_NCURSESW_CURSES_H - if should be used # HAVE_NCURSES_CURSES_H - if should be used # # (These preprocessor symbols are discussed later in this document.) # # The following output variable is defined by this macro; it is precious # and may be overridden on the ./configure command line: # # CURSES_LIB - library to add to xxx_LDADD # # The library listed in CURSES_LIB is NOT added to LIBS by default. You # need to add CURSES_LIB to the appropriate xxx_LDADD line in your # Makefile.am. For example: # # prog_LDADD = @CURSES_LIB@ # # If CURSES_LIB is set on the configure command line (such as by running # "./configure CURSES_LIB=-lmycurses"), then the only header searched for # is . The user may use the CPPFLAGS precious variable to # override the standard #include search path. If the user needs to # specify an alternative path for a library (such as for a non-standard # NcurseW), the user should use the LDFLAGS variable. # # The following shell variables may be defined by this macro: # # ax_cv_curses - set to "yes" if any Curses library found # ax_cv_curses_enhanced - set to "yes" if Enhanced functions present # ax_cv_curses_color - set to "yes" if color functions present # ax_cv_curses_obsolete - set to "yes" if obsolete features present # # ax_cv_ncursesw - set to "yes" if NcursesW library found # ax_cv_ncurses - set to "yes" if Ncurses library found # ax_cv_plaincurses - set to "yes" if plain Curses library found # ax_cv_curses_which - set to "ncursesw", "ncurses", "plaincurses" or "no" # # These variables can be used in your configure.ac to determine the level # of support you need from the Curses library. For example, if you must # have either Ncurses or NcursesW, you could include: # # AX_WITH_CURSES # if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then # AX_MSG_ERROR([requires either NcursesW or Ncurses library]) # fi # # If any Curses library will do (but one must be present and must support # color), you could use: # # AX_WITH_CURSES # if test "x$ax_cv_curses" != xyes || test "x$ax_cv_curses_color" != xyes; then # AC_MSG_ERROR([requires an X/Open-compatible Curses library with color]) # fi # # Certain preprocessor symbols and shell variables defined by this macro # can be used to determine various features of the Curses library. In # particular, HAVE_CURSES and ax_cv_curses are defined if the Curses # library found conforms to the traditional SysV and/or X/Open Base Curses # definition. Any working Curses library conforms to this level. # # HAVE_CURSES_ENHANCED and ax_cv_curses_enhanced are defined if the # library supports the X/Open Enhanced Curses definition. In particular, # the wide-character types attr_t, cchar_t and wint_t, the functions # wattr_set() and wget_wch() and the macros WA_NORMAL and _XOPEN_CURSES # are checked. The Ncurses library does NOT conform to this definition, # although NcursesW does. # # HAVE_CURSES_COLOR and ax_cv_curses_color are defined if the library # supports color functions and macros such as COLOR_PAIR, A_COLOR, # COLOR_WHITE, COLOR_RED and init_pair(). These are NOT part of the # X/Open Base Curses definition, but are part of the Enhanced set of # functions. The Ncurses library DOES support these functions, as does # NcursesW. # # HAVE_CURSES_OBSOLETE and ax_cv_curses_obsolete are defined if the # library supports certain features present in SysV and BSD Curses but not # defined in the X/Open definition. In particular, the functions # getattrs(), getcurx() and getmaxx() are checked. # # To use the HAVE_xxx_H preprocessor symbols, insert the following into # your system.h (or equivalent) header file: # # #if defined HAVE_NCURSESW_CURSES_H # # include # #elif defined HAVE_NCURSESW_H # # include # #elif defined HAVE_NCURSES_CURSES_H # # include # #elif defined HAVE_NCURSES_H # # include # #elif defined HAVE_CURSES_H # # include # #else # # error "SysV or X/Open-compatible Curses header file required" # #endif # # For previous users of this macro: you should not need to change anything # in your configure.ac or Makefile.am, as the previous (serial 10) # semantics are still valid. However, you should update your system.h (or # equivalent) header file to the fragment shown above. You are encouraged # also to make use of the extended functionality provided by this version # of AX_WITH_CURSES, as well as in the additional macros # AX_WITH_CURSES_PANEL, AX_WITH_CURSES_MENU and AX_WITH_CURSES_FORM. # # LICENSE # # Copyright (c) 2009 Mark Pulford # Copyright (c) 2009 Damian Pietras # Copyright (c) 2012 Reuben Thomas # Copyright (c) 2011 John Zaitseff # # 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, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 13 AU_ALIAS([MP_WITH_CURSES], [AX_WITH_CURSES]) AC_DEFUN([AX_WITH_CURSES], [ AC_ARG_VAR([CURSES_LIB], [linker library for Curses, e.g. -lcurses]) AC_ARG_WITH([ncurses], [AS_HELP_STRING([--with-ncurses], [force the use of Ncurses or NcursesW])], [], [with_ncurses=check]) AC_ARG_WITH([ncursesw], [AS_HELP_STRING([--without-ncursesw], [do not use NcursesW (wide character support)])], [], [with_ncursesw=check]) ax_saved_LIBS=$LIBS AS_IF([test "x$with_ncurses" = xyes || test "x$with_ncursesw" = xyes], [ax_with_plaincurses=no], [ax_with_plaincurses=check]) ax_cv_curses_which=no # Test for NcursesW AS_IF([test "x$CURSES_LIB" = x && test "x$with_ncursesw" != xno], [ LIBS="$ax_saved_LIBS -lncursesw" AC_CACHE_CHECK([for NcursesW wide-character library], [ax_cv_ncursesw], [ AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])], [ax_cv_ncursesw=yes], [ax_cv_ncursesw=no]) ]) AS_IF([test "x$ax_cv_ncursesw" = xno && test "x$with_ncursesw" = xyes], [ AC_MSG_ERROR([--with-ncursesw specified but could not find NcursesW library]) ]) AS_IF([test "x$ax_cv_ncursesw" = xyes], [ ax_cv_curses=yes ax_cv_curses_which=ncursesw CURSES_LIB="-lncursesw" AC_DEFINE([HAVE_NCURSESW], [1], [Define to 1 if the NcursesW library is present]) AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present]) AC_CACHE_CHECK([for working ncursesw/curses.h], [ax_cv_header_ncursesw_curses_h], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @%:@define _XOPEN_SOURCE_EXTENDED 1 @%:@include ]], [[ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; attr_t d = WA_NORMAL; cchar_t e; wint_t f; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); wattr_set(stdscr, d, 0, NULL); wget_wch(stdscr, &f); ]])], [ax_cv_header_ncursesw_curses_h=yes], [ax_cv_header_ncursesw_curses_h=no]) ]) AS_IF([test "x$ax_cv_header_ncursesw_curses_h" = xyes], [ ax_cv_curses_enhanced=yes ax_cv_curses_color=yes ax_cv_curses_obsolete=yes AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions]) AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)]) AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features]) AC_DEFINE([HAVE_NCURSESW_CURSES_H], [1], [Define to 1 if is present]) ]) AC_CACHE_CHECK([for working ncursesw.h], [ax_cv_header_ncursesw_h], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @%:@define _XOPEN_SOURCE_EXTENDED 1 @%:@include ]], [[ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; attr_t d = WA_NORMAL; cchar_t e; wint_t f; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); wattr_set(stdscr, d, 0, NULL); wget_wch(stdscr, &f); ]])], [ax_cv_header_ncursesw_h=yes], [ax_cv_header_ncursesw_h=no]) ]) AS_IF([test "x$ax_cv_header_ncursesw_h" = xyes], [ ax_cv_curses_enhanced=yes ax_cv_curses_color=yes ax_cv_curses_obsolete=yes AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions]) AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)]) AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features]) AC_DEFINE([HAVE_NCURSESW_H], [1], [Define to 1 if is present]) ]) AC_CACHE_CHECK([for working ncurses.h], [ax_cv_header_ncurses_h_with_ncursesw], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @%:@define _XOPEN_SOURCE_EXTENDED 1 @%:@include ]], [[ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; attr_t d = WA_NORMAL; cchar_t e; wint_t f; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); wattr_set(stdscr, d, 0, NULL); wget_wch(stdscr, &f); ]])], [ax_cv_header_ncurses_h_with_ncursesw=yes], [ax_cv_header_ncurses_h_with_ncursesw=no]) ]) AS_IF([test "x$ax_cv_header_ncurses_h_with_ncursesw" = xyes], [ ax_cv_curses_enhanced=yes ax_cv_curses_color=yes ax_cv_curses_obsolete=yes AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions]) AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)]) AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features]) AC_DEFINE([HAVE_NCURSES_H], [1], [Define to 1 if is present]) ]) AS_IF([test "x$ax_cv_header_ncursesw_curses_h" = xno && test "x$ax_cv_header_ncursesw_h" = xno && test "x$ax_cv_header_ncurses_h_with_ncursesw" = xno], [ AC_MSG_WARN([could not find a working ncursesw/curses.h, ncursesw.h or ncurses.h]) ]) ]) ]) # Test for Ncurses AS_IF([test "x$CURSES_LIB" = x && test "x$with_ncurses" != xno && test "x$ax_cv_curses_which" = xno], [ LIBS="$ax_saved_LIBS -lncurses" AC_CACHE_CHECK([for Ncurses library], [ax_cv_ncurses], [ AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])], [ax_cv_ncurses=yes], [ax_cv_ncurses=no]) ]) AS_IF([test "x$ax_cv_ncurses" = xno && test "x$with_ncurses" = xyes], [ AC_MSG_ERROR([--with-ncurses specified but could not find Ncurses library]) ]) AS_IF([test "x$ax_cv_ncurses" = xyes], [ ax_cv_curses=yes ax_cv_curses_which=ncurses CURSES_LIB="-lncurses" AC_DEFINE([HAVE_NCURSES], [1], [Define to 1 if the Ncurses library is present]) AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present]) AC_CACHE_CHECK([for working ncurses/curses.h], [ax_cv_header_ncurses_curses_h], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @%:@include ]], [[ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); ]])], [ax_cv_header_ncurses_curses_h=yes], [ax_cv_header_ncurses_curses_h=no]) ]) AS_IF([test "x$ax_cv_header_ncurses_curses_h" = xyes], [ ax_cv_curses_color=yes ax_cv_curses_obsolete=yes AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)]) AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features]) AC_DEFINE([HAVE_NCURSES_CURSES_H], [1], [Define to 1 if is present]) ]) AC_CACHE_CHECK([for working ncurses.h], [ax_cv_header_ncurses_h], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @%:@include ]], [[ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); ]])], [ax_cv_header_ncurses_h=yes], [ax_cv_header_ncurses_h=no]) ]) AS_IF([test "x$ax_cv_header_ncurses_h" = xyes], [ ax_cv_curses_color=yes ax_cv_curses_obsolete=yes AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)]) AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features]) AC_DEFINE([HAVE_NCURSES_H], [1], [Define to 1 if is present]) ]) AS_IF([test "x$ax_cv_header_ncurses_curses_h" = xno && test "x$ax_cv_header_ncurses_h" = xno], [ AC_MSG_WARN([could not find a working ncurses/curses.h or ncurses.h]) ]) ]) ]) # Test for plain Curses (or if CURSES_LIB was set by user) AS_IF([test "x$with_plaincurses" != xno && test "x$ax_cv_curses_which" = xno], [ AS_IF([test "x$CURSES_LIB" != x], [ LIBS="$ax_saved_LIBS $CURSES_LIB" ], [ LIBS="$ax_saved_LIBS -lcurses" ]) AC_CACHE_CHECK([for Curses library], [ax_cv_plaincurses], [ AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])], [ax_cv_plaincurses=yes], [ax_cv_plaincurses=no]) ]) AS_IF([test "x$ax_cv_plaincurses" = xyes], [ ax_cv_curses=yes ax_cv_curses_which=plaincurses AS_IF([test "x$CURSES_LIB" = x], [ CURSES_LIB="-lcurses" ]) AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present]) # Check for base conformance (and header file) AC_CACHE_CHECK([for working curses.h], [ax_cv_header_curses_h], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @%:@include ]], [[ chtype a = A_BOLD; int b = KEY_LEFT; initscr(); ]])], [ax_cv_header_curses_h=yes], [ax_cv_header_curses_h=no]) ]) AS_IF([test "x$ax_cv_header_curses_h" = xyes], [ AC_DEFINE([HAVE_CURSES_H], [1], [Define to 1 if is present]) # Check for X/Open Enhanced conformance AC_CACHE_CHECK([for X/Open Enhanced Curses conformance], [ax_cv_plaincurses_enhanced], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @%:@define _XOPEN_SOURCE_EXTENDED 1 @%:@include @%:@ifndef _XOPEN_CURSES @%:@error "this Curses library is not enhanced" "this Curses library is not enhanced" @%:@endif ]], [[ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; attr_t d = WA_NORMAL; cchar_t e; wint_t f; initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); wattr_set(stdscr, d, 0, NULL); wget_wch(stdscr, &f); ]])], [ax_cv_plaincurses_enhanced=yes], [ax_cv_plaincurses_enhanced=no]) ]) AS_IF([test "x$ax_cv_plaincurses_enhanced" = xyes], [ ax_cv_curses_enhanced=yes ax_cv_curses_color=yes AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions]) AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)]) ]) # Check for color functions AC_CACHE_CHECK([for Curses color functions], [ax_cv_plaincurses_color], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @%:@define _XOPEN_SOURCE_EXTENDED 1 @%:@include ]], [[ chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); ]])], [ax_cv_plaincurses_color=yes], [ax_cv_plaincurses_color=no]) ]) AS_IF([test "x$ax_cv_plaincurses_color" = xyes], [ ax_cv_curses_color=yes AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)]) ]) # Check for obsolete functions AC_CACHE_CHECK([for obsolete Curses functions], [ax_cv_plaincurses_obsolete], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ @%:@include ]], [[ chtype a = A_BOLD; int b = KEY_LEFT; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); ]])], [ax_cv_plaincurses_obsolete=yes], [ax_cv_plaincurses_obsolete=no]) ]) AS_IF([test "x$ax_cv_plaincurses_obsolete" = xyes], [ ax_cv_curses_obsolete=yes AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features]) ]) ]) AS_IF([test "x$ax_cv_header_curses_h" = xno], [ AC_MSG_WARN([could not find a working curses.h]) ]) ]) ]) AS_IF([test "x$ax_cv_curses" != xyes], [ax_cv_curses=no]) AS_IF([test "x$ax_cv_curses_enhanced" != xyes], [ax_cv_curses_enhanced=no]) AS_IF([test "x$ax_cv_curses_color" != xyes], [ax_cv_curses_color=no]) AS_IF([test "x$ax_cv_curses_obsolete" != xyes], [ax_cv_curses_obsolete=no]) LIBS=$ax_saved_LIBS ])dnl lnav-0.7.0/compile000775 000765 000024 00000016245 12211635053 014314 0ustar00stackstaff000000 000000 #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2013 Free Software Foundation, Inc. # Written by Tom Tromey . # # 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, see . # 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. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # 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-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: lnav-0.7.0/config.guess000775 000765 000024 00000130361 12264662106 015261 0ustar00stackstaff000000 000000 #! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-06-10' # This file 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, see . # # 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. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD # # Please send patches with a ChangeLog entry to config-patches@gnu.org. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="gnulibc1" ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; or1k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp 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` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: lnav-0.7.0/config.sub000775 000765 000024 00000105301 12264662106 014720 0ustar00stackstaff000000 000000 #! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2013 Free Software Foundation, Inc. timestamp='2013-04-24' # This file 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, see . # # 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. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 \ | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or1k-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: lnav-0.7.0/configure000775 000765 000024 00000770235 12313323143 014650 0ustar00stackstaff000000 000000 #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for lnav 0.7.0. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 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. as_myself= 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 # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # 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. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} 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 test -x / || 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 : export CONFIG_SHELL # 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. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 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 $0: lnav@googlegroups.com about your system, including any $0: error possibly output before this message. Then install $0: a modern shell, or manually run the script under such a $0: shell if you do 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_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_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 STATUS 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=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&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; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # 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 -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' 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 as_test_x='test -x' as_executable_p=as_fn_executable_p # 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, old GNU/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='lnav' PACKAGE_TARNAME='lnav' PACKAGE_VERSION='0.7.0' PACKAGE_STRING='lnav 0.7.0' PACKAGE_BUGREPORT='lnav@googlegroups.com' PACKAGE_URL='' ac_unique_file="src/lnav.cc" ac_default_prefix=/usr # 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 LIBOBJS STATIC_LDFLAGS SQLITE3_VERSION SQLITE3_LIBS SQLITE3_LDFLAGS SQLITE3_CFLAGS READLINE_CFLAGS READLINE_LIBS PCRE_CFLAGS PCRE_LIBS CURSES_LIB EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE ac_ct_CC CFLAGS CC BZIP2_CMD SQLITE3_CMD pkgpyexecdir pyexecdir pkgpythondir pythondir PYTHON_PLATFORM PYTHON_EXEC_PREFIX PYTHON_PREFIX PYTHON_VERSION PYTHON LN_S RANLIB CFLAGS_PG am__fastdepCXX_FALSE am__fastdepCXX_TRUE CXXDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CXX CPPFLAGS LDFLAGS CXXFLAGS CXX abssrcdir host_os host_vendor host_cpu host build_os build_vendor build_cpu build AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V 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_silent_rules enable_dependency_tracking enable_profiling with_ncurses with_ncursesw with_pcre with_readline with_sqlite3 enable_static ' ac_precious_vars='build_alias host_alias target_alias CXX CXXFLAGS LDFLAGS LIBS CPPFLAGS CCC PYTHON CC CFLAGS CPP CURSES_LIB' # 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= ;; *) 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 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 lnav 0.7.0 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/lnav] --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 System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of lnav 0.7.0:";; 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-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-profiling Compile with gprof(1) profiling support --disable-static Disable static linking Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-ncurses force the use of Ncurses or NcursesW --without-ncursesw do not use NcursesW (wide character support) --with-pcre[=prefix] --with-readline[=prefix] compile xmlreadline part (via libreadline check) --with-sqlite3=[ARG] use SQLite 3 library [default=yes], optionally specify the prefix for sqlite3 library Some influential environment variables: CXX C++ compiler command CXXFLAGS 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 PYTHON the Python interpreter CC C compiler command CFLAGS C compiler flags CPP C preprocessor CURSES_LIB linker library for Curses, e.g. -lcurses 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 lnav configure 0.7.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 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_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_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_cxx_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; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # 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; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # 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; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval () { return $2; } static unsigned long int ulongval () { return $2; } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 &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; } > conftest.i && { 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; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # 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 eval \${$3+:} false; 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; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" 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=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _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; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl # 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 || 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; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # 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 eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; 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.i 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;} ( $as_echo "## ------------------------------------ ## ## Report this to lnav@googlegroups.com ## ## ------------------------------------ ##" ) | 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 eval \${$3+:} false; 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; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # 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 eval \${$3+:} false; 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; ${as_lineno_stack:+:} 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 lnav $as_me 0.7.0, which was generated by GNU Autoconf 2.69. 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 $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" 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 $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" 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 $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" 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 $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" 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 # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac 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" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } 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 am__api_version='1.14' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi 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 ${ac_cv_path_install+:} false; 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 as_fn_executable_p "$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; } # 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 ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file 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 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 if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done 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; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file 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 --is-lightweight"; then am_missing_run="$MISSING " 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 ${ac_cv_prog_STRIP+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_ac_ct_STRIP+:} false; 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 as_fn_executable_p "$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 ${ac_cv_path_mkdir+:} false; 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 as_fn_executable_p "$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; } 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 ${ac_cv_prog_AWK+:} false; 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 as_fn_executable_p "$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 eval \${ac_cv_prog_make_${ac_make}_set+:} false; 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 # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' 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='lnav' VERSION='0.7.0' 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"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac for defdir in /opt/local /usr/local /usr /; do if test -d "$defdir/include"; then CPPFLAGS="$CPPFLAGS -I$defdir/include" fi if test -d "$defdir/lib"; then LDFLAGS="$LDFLAGS -L$defdir/lib" fi if test -d "$defdir/lib64"; then LDFLAGS="$LDFLAGS -L$defdir/lib64" fi if test -d "$defdir/lib/x86_64-linux-gnu"; then LDFLAGS="$LDFLAGS -L$defdir/lib/x86_64-linux-gnu" fi done case x$srcdir in x/*) abssrcdir=$srcdir ;; *) abssrcdir=`pwd`/$srcdir ;; esac ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC 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 ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CXX="$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 CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC 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 ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CXX="$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_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" 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 CXX=$ac_ct_CXX fi fi fi fi # 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_error 77 "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 ${ac_cv_objext+:} false; 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 ${ac_cv_cxx_compiler_gnu+:} false; 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_cxx_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_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_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_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi 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='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CXX" 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 ${am_cv_CXX_dependencies_compiler_type+:} false; 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". rm -rf conftest.dir 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_CXX_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 10 /bin/sh. echo '/* dummy */' > 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 ;; msvc7 | msvc7msys | 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_CXX_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CXX_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 $as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then am__fastdepCXX_TRUE= am__fastdepCXX_FALSE='#' else am__fastdepCXX_TRUE='#' am__fastdepCXX_FALSE= fi CPPFLAGS="$CPPFLAGS -D_ISOC99_SOURCE -D__STDC_LIMIT_MACROS" # CFLAGS=`echo $CFLAGS | sed 's/-O2//g'` # CXXFLAGS=`echo $CXXFLAGS | sed 's/-O2//g'` # Check whether --enable-profiling was given. if test "${enable_profiling+set}" = set; then : enableval=$enable_profiling; fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking gprof(4) profiling support" >&5 $as_echo_n "checking gprof(4) profiling support... " >&6; } if test x"${enable_profiling}" = x"yes" ; then CFLAGS="$CFLAGS -pg -gstabs" CXXFLAGS="$CXXFLAGS -pg -gstabs" LDFLAGS="$LDFLAGS -pg" else enable_profiling=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_profiling" >&5 $as_echo "$enable_profiling" >&6; } 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 ${ac_cv_prog_RANLIB+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_ac_ct_RANLIB+:} false; 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 as_fn_executable_p "$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 { $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 { $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 eval \${ac_cv_prog_make_${ac_make}_set+:} false; 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 if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON version is >= 2.4" >&5 $as_echo_n "checking whether $PYTHON version is >= 2.4... " >&6; } prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '2.4'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5 ($PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; 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" >&5 $as_echo "no" >&6; } as_fn_error $? "Python interpreter is too old" "$LINENO" 5 fi am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Python interpreter with version >= 2.4" >&5 $as_echo_n "checking for a Python interpreter with version >= 2.4... " >&6; } if ${am_cv_pathless_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else for am_cv_pathless_PYTHON in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do test "$am_cv_pathless_PYTHON" = none && break prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '2.4'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5 ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then : break fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_pathless_PYTHON" >&5 $as_echo "$am_cv_pathless_PYTHON" >&6; } # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args. set dummy $am_cv_pathless_PYTHON; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PYTHON+:} false; then : $as_echo_n "(cached) " >&6 else case $PYTHON in [\\/]* | ?:[\\/]*) ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. ;; *) 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext" $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 ;; esac fi PYTHON=$ac_cv_path_PYTHON if test -n "$PYTHON"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 $as_echo "$PYTHON" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi am_display_PYTHON=$am_cv_pathless_PYTHON fi if test "$PYTHON" = :; then as_fn_error $? "no suitable Python interpreter found" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5 $as_echo_n "checking for $am_display_PYTHON version... " >&6; } if ${am_cv_python_version+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5 $as_echo "$am_cv_python_version" >&6; } PYTHON_VERSION=$am_cv_python_version PYTHON_PREFIX='${prefix}' PYTHON_EXEC_PREFIX='${exec_prefix}' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5 $as_echo_n "checking for $am_display_PYTHON platform... " >&6; } if ${am_cv_python_platform+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5 $as_echo "$am_cv_python_platform" >&6; } PYTHON_PLATFORM=$am_cv_python_platform # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[:3] == '2.7': can_use_sysconfig = 0 except ImportError: pass" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5 $as_echo_n "checking for $am_display_PYTHON script directory... " >&6; } if ${am_cv_python_pythondir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5 $as_echo "$am_cv_python_pythondir" >&6; } pythondir=$am_cv_python_pythondir pkgpythondir=\${pythondir}/$PACKAGE { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5 $as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; } if ${am_cv_python_pyexecdir+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5 $as_echo "$am_cv_python_pyexecdir" >&6; } pyexecdir=$am_cv_python_pyexecdir pkgpyexecdir=\${pyexecdir}/$PACKAGE fi # Extract the first word of "sqlite3", so it can be a program name with args. set dummy sqlite3; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_SQLITE3_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $SQLITE3_CMD in [\\/]* | ?:[\\/]*) ac_cv_path_SQLITE3_CMD="$SQLITE3_CMD" # Let the user override the test with a path. ;; *) 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SQLITE3_CMD="$as_dir/$ac_word$ac_exec_ext" $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 ;; esac fi SQLITE3_CMD=$ac_cv_path_SQLITE3_CMD if test -n "$SQLITE3_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SQLITE3_CMD" >&5 $as_echo "$SQLITE3_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$SQLITE3_CMD" = x""; then as_fn_error $? "The sqlite3 command is required" "$LINENO" 5 fi # Extract the first word of "bzip2", so it can be a program name with args. set dummy bzip2; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_BZIP2_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $BZIP2_CMD in [\\/]* | ?:[\\/]*) ac_cv_path_BZIP2_CMD="$BZIP2_CMD" # Let the user override the test with a path. ;; *) 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_BZIP2_CMD="$as_dir/$ac_word$ac_exec_ext" $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 ;; esac fi BZIP2_CMD=$ac_cv_path_BZIP2_CMD if test -n "$BZIP2_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $BZIP2_CMD" >&5 $as_echo "$BZIP2_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } 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 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 ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_ac_ct_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$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 ${ac_cv_prog_ac_ct_CC+:} false; 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 as_fn_executable_p "$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 { $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 ${ac_cv_c_compiler_gnu+:} false; 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 ${ac_cv_prog_cc_g+:} false; 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 ${ac_cv_prog_cc_c89+:} false; 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 struct stat; /* 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 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 whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" 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 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 ${am_cv_CC_dependencies_compiler_type+:} false; 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". rm -rf conftest.dir 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 10 /bin/sh. echo '/* dummy */' > 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 ;; msvc7 | msvc7msys | 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 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 ${ac_cv_prog_CPP+:} false; 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.i 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.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i 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.i 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.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i 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 ${ac_cv_path_GREP+:} false; 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" as_fn_executable_p "$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 ${ac_cv_path_EGREP+:} false; 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" as_fn_executable_p "$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 ${ac_cv_header_stdc+:} false; 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 # 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 " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of off_t" >&5 $as_echo_n "checking size of off_t... " >&6; } if ${ac_cv_sizeof_off_t+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (off_t))" "ac_cv_sizeof_off_t" "$ac_includes_default"; then : else if test "$ac_cv_type_off_t" = 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 77 "cannot compute sizeof (off_t) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_off_t=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_off_t" >&5 $as_echo "$ac_cv_sizeof_off_t" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_OFF_T $ac_cv_sizeof_off_t _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5 $as_echo_n "checking size of size_t... " >&6; } if ${ac_cv_sizeof_size_t+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$ac_includes_default"; then : else if test "$ac_cv_type_size_t" = 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 77 "cannot compute sizeof (size_t) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_size_t=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5 $as_echo "$ac_cv_sizeof_size_t" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_SIZE_T $ac_cv_sizeof_size_t _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } if ${ac_cv_struct_tm+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct tm tm; int *p = &tm.tm_sec; return !p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_tm=time.h else ac_cv_struct_tm=sys/time.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 $as_echo "$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then $as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct tm" "tm_zone" "ac_cv_member_struct_tm_tm_zone" "#include #include <$ac_cv_struct_tm> " if test "x$ac_cv_member_struct_tm_tm_zone" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_TM_TM_ZONE 1 _ACEOF fi if test "$ac_cv_member_struct_tm_tm_zone" = yes; then $as_echo "#define HAVE_TM_ZONE 1" >>confdefs.h else ac_fn_c_check_decl "$LINENO" "tzname" "ac_cv_have_decl_tzname" "#include " if test "x$ac_cv_have_decl_tzname" = xyes; then : ac_have_decl=1 else ac_have_decl=0 fi cat >>confdefs.h <<_ACEOF #define HAVE_DECL_TZNAME $ac_have_decl _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tzname" >&5 $as_echo_n "checking for tzname... " >&6; } if ${ac_cv_var_tzname+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if !HAVE_DECL_TZNAME extern char *tzname[]; #endif int main () { return tzname[0][0]; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_var_tzname=yes else ac_cv_var_tzname=no 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_var_tzname" >&5 $as_echo "$ac_cv_var_tzname" >&6; } if test $ac_cv_var_tzname = yes; then $as_echo "#define HAVE_TZNAME 1" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing openpty" >&5 $as_echo_n "checking for library containing openpty... " >&6; } if ${ac_cv_search_openpty+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS 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 openpty (); int main () { return openpty (); ; return 0; } _ACEOF for ac_lib in '' util; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_openpty=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_openpty+:} false; then : break fi done if ${ac_cv_search_openpty+:} false; then : else ac_cv_search_openpty=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_openpty" >&5 $as_echo "$ac_cv_search_openpty" >&6; } ac_res=$ac_cv_search_openpty if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gzseek" >&5 $as_echo_n "checking for library containing gzseek... " >&6; } if ${ac_cv_search_gzseek+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS 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 gzseek (); int main () { return gzseek (); ; return 0; } _ACEOF for ac_lib in '' z; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gzseek=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gzseek+:} false; then : break fi done if ${ac_cv_search_gzseek+:} false; then : else ac_cv_search_gzseek=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gzseek" >&5 $as_echo "$ac_cv_search_gzseek" >&6; } ac_res=$ac_cv_search_gzseek if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else as_fn_error $? "libz required to build" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing BZ2_bzopen" >&5 $as_echo_n "checking for library containing BZ2_bzopen... " >&6; } if ${ac_cv_search_BZ2_bzopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS 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 BZ2_bzopen (); int main () { return BZ2_bzopen (); ; return 0; } _ACEOF for ac_lib in '' bz2; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_BZ2_bzopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_BZ2_bzopen+:} false; then : break fi done if ${ac_cv_search_BZ2_bzopen+:} false; then : else ac_cv_search_BZ2_bzopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_BZ2_bzopen" >&5 $as_echo "$ac_cv_search_BZ2_bzopen" >&6; } ac_res=$ac_cv_search_BZ2_bzopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS 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 dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing backtrace" >&5 $as_echo_n "checking for library containing backtrace... " >&6; } if ${ac_cv_search_backtrace+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS 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 backtrace (); int main () { return backtrace (); ; return 0; } _ACEOF for ac_lib in '' execinfo; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_backtrace=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_backtrace+:} false; then : break fi done if ${ac_cv_search_backtrace+:} false; then : else ac_cv_search_backtrace=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_backtrace" >&5 $as_echo "$ac_cv_search_backtrace" >&6; } ac_res=$ac_cv_search_backtrace if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi # Sometimes, curses depends on these libraries being linked in... { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cur_term" >&5 $as_echo_n "checking for library containing cur_term... " >&6; } if ${ac_cv_search_cur_term+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS 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 cur_term (); int main () { return cur_term (); ; return 0; } _ACEOF for ac_lib in '' tinfo; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_cur_term=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_cur_term+:} false; then : break fi done if ${ac_cv_search_cur_term+:} false; then : else ac_cv_search_cur_term=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_cur_term" >&5 $as_echo "$ac_cv_search_cur_term" >&6; } ac_res=$ac_cv_search_cur_term if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing Gpm_Open" >&5 $as_echo_n "checking for library containing Gpm_Open... " >&6; } if ${ac_cv_search_Gpm_Open+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS 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 Gpm_Open (); int main () { return Gpm_Open (); ; return 0; } _ACEOF for ac_lib in '' gpm; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_Gpm_Open=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_Gpm_Open+:} false; then : break fi done if ${ac_cv_search_Gpm_Open+:} false; then : else ac_cv_search_Gpm_Open=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_Gpm_Open" >&5 $as_echo "$ac_cv_search_Gpm_Open" >&6; } ac_res=$ac_cv_search_Gpm_Open if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi for ac_header in execinfo.h pty.h util.h zlib.h bzlib.h libutil.h sys/ttydefaults.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" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Check whether --with-ncurses was given. if test "${with_ncurses+set}" = set; then : withval=$with_ncurses; else with_ncurses=check fi # Check whether --with-ncursesw was given. if test "${with_ncursesw+set}" = set; then : withval=$with_ncursesw; else with_ncursesw=check fi ax_saved_LIBS=$LIBS if test "x$with_ncurses" = xyes || test "x$with_ncursesw" = xyes; then : ax_with_plaincurses=no else ax_with_plaincurses=check fi ax_cv_curses_which=no # Test for NcursesW if test "x$CURSES_LIB" = x && test "x$with_ncursesw" != xno; then : LIBS="$ax_saved_LIBS -lncursesw" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NcursesW wide-character library" >&5 $as_echo_n "checking for NcursesW wide-character library... " >&6; } if ${ax_cv_ncursesw+:} false; then : $as_echo_n "(cached) " >&6 else 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 initscr (); int main () { return initscr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_ncursesw=yes else ax_cv_ncursesw=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_ncursesw" >&5 $as_echo "$ax_cv_ncursesw" >&6; } if test "x$ax_cv_ncursesw" = xno && test "x$with_ncursesw" = xyes; then : as_fn_error $? "--with-ncursesw specified but could not find NcursesW library" "$LINENO" 5 fi if test "x$ax_cv_ncursesw" = xyes; then : ax_cv_curses=yes ax_cv_curses_which=ncursesw CURSES_LIB="-lncursesw" $as_echo "#define HAVE_NCURSESW 1" >>confdefs.h $as_echo "#define HAVE_CURSES 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working ncursesw/curses.h" >&5 $as_echo_n "checking for working ncursesw/curses.h... " >&6; } if ${ax_cv_header_ncursesw_curses_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _XOPEN_SOURCE_EXTENDED 1 #include int main () { chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; attr_t d = WA_NORMAL; cchar_t e; wint_t f; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); wattr_set(stdscr, d, 0, NULL); wget_wch(stdscr, &f); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_header_ncursesw_curses_h=yes else ax_cv_header_ncursesw_curses_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_header_ncursesw_curses_h" >&5 $as_echo "$ax_cv_header_ncursesw_curses_h" >&6; } if test "x$ax_cv_header_ncursesw_curses_h" = xyes; then : ax_cv_curses_enhanced=yes ax_cv_curses_color=yes ax_cv_curses_obsolete=yes $as_echo "#define HAVE_CURSES_ENHANCED 1" >>confdefs.h $as_echo "#define HAVE_CURSES_COLOR 1" >>confdefs.h $as_echo "#define HAVE_CURSES_OBSOLETE 1" >>confdefs.h $as_echo "#define HAVE_NCURSESW_CURSES_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working ncursesw.h" >&5 $as_echo_n "checking for working ncursesw.h... " >&6; } if ${ax_cv_header_ncursesw_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _XOPEN_SOURCE_EXTENDED 1 #include int main () { chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; attr_t d = WA_NORMAL; cchar_t e; wint_t f; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); wattr_set(stdscr, d, 0, NULL); wget_wch(stdscr, &f); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_header_ncursesw_h=yes else ax_cv_header_ncursesw_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_header_ncursesw_h" >&5 $as_echo "$ax_cv_header_ncursesw_h" >&6; } if test "x$ax_cv_header_ncursesw_h" = xyes; then : ax_cv_curses_enhanced=yes ax_cv_curses_color=yes ax_cv_curses_obsolete=yes $as_echo "#define HAVE_CURSES_ENHANCED 1" >>confdefs.h $as_echo "#define HAVE_CURSES_COLOR 1" >>confdefs.h $as_echo "#define HAVE_CURSES_OBSOLETE 1" >>confdefs.h $as_echo "#define HAVE_NCURSESW_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working ncurses.h" >&5 $as_echo_n "checking for working ncurses.h... " >&6; } if ${ax_cv_header_ncurses_h_with_ncursesw+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _XOPEN_SOURCE_EXTENDED 1 #include int main () { chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; attr_t d = WA_NORMAL; cchar_t e; wint_t f; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); wattr_set(stdscr, d, 0, NULL); wget_wch(stdscr, &f); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_header_ncurses_h_with_ncursesw=yes else ax_cv_header_ncurses_h_with_ncursesw=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_header_ncurses_h_with_ncursesw" >&5 $as_echo "$ax_cv_header_ncurses_h_with_ncursesw" >&6; } if test "x$ax_cv_header_ncurses_h_with_ncursesw" = xyes; then : ax_cv_curses_enhanced=yes ax_cv_curses_color=yes ax_cv_curses_obsolete=yes $as_echo "#define HAVE_CURSES_ENHANCED 1" >>confdefs.h $as_echo "#define HAVE_CURSES_COLOR 1" >>confdefs.h $as_echo "#define HAVE_CURSES_OBSOLETE 1" >>confdefs.h $as_echo "#define HAVE_NCURSES_H 1" >>confdefs.h fi if test "x$ax_cv_header_ncursesw_curses_h" = xno && test "x$ax_cv_header_ncursesw_h" = xno && test "x$ax_cv_header_ncurses_h_with_ncursesw" = xno; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find a working ncursesw/curses.h, ncursesw.h or ncurses.h" >&5 $as_echo "$as_me: WARNING: could not find a working ncursesw/curses.h, ncursesw.h or ncurses.h" >&2;} fi fi fi # Test for Ncurses if test "x$CURSES_LIB" = x && test "x$with_ncurses" != xno && test "x$ax_cv_curses_which" = xno; then : LIBS="$ax_saved_LIBS -lncurses" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ncurses library" >&5 $as_echo_n "checking for Ncurses library... " >&6; } if ${ax_cv_ncurses+:} false; then : $as_echo_n "(cached) " >&6 else 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 initscr (); int main () { return initscr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_ncurses=yes else ax_cv_ncurses=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_ncurses" >&5 $as_echo "$ax_cv_ncurses" >&6; } if test "x$ax_cv_ncurses" = xno && test "x$with_ncurses" = xyes; then : as_fn_error $? "--with-ncurses specified but could not find Ncurses library" "$LINENO" 5 fi if test "x$ax_cv_ncurses" = xyes; then : ax_cv_curses=yes ax_cv_curses_which=ncurses CURSES_LIB="-lncurses" $as_echo "#define HAVE_NCURSES 1" >>confdefs.h $as_echo "#define HAVE_CURSES 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working ncurses/curses.h" >&5 $as_echo_n "checking for working ncurses/curses.h... " >&6; } if ${ax_cv_header_ncurses_curses_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_header_ncurses_curses_h=yes else ax_cv_header_ncurses_curses_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_header_ncurses_curses_h" >&5 $as_echo "$ax_cv_header_ncurses_curses_h" >&6; } if test "x$ax_cv_header_ncurses_curses_h" = xyes; then : ax_cv_curses_color=yes ax_cv_curses_obsolete=yes $as_echo "#define HAVE_CURSES_COLOR 1" >>confdefs.h $as_echo "#define HAVE_CURSES_OBSOLETE 1" >>confdefs.h $as_echo "#define HAVE_NCURSES_CURSES_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working ncurses.h" >&5 $as_echo_n "checking for working ncurses.h... " >&6; } if ${ax_cv_header_ncurses_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_header_ncurses_h=yes else ax_cv_header_ncurses_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_header_ncurses_h" >&5 $as_echo "$ax_cv_header_ncurses_h" >&6; } if test "x$ax_cv_header_ncurses_h" = xyes; then : ax_cv_curses_color=yes ax_cv_curses_obsolete=yes $as_echo "#define HAVE_CURSES_COLOR 1" >>confdefs.h $as_echo "#define HAVE_CURSES_OBSOLETE 1" >>confdefs.h $as_echo "#define HAVE_NCURSES_H 1" >>confdefs.h fi if test "x$ax_cv_header_ncurses_curses_h" = xno && test "x$ax_cv_header_ncurses_h" = xno; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find a working ncurses/curses.h or ncurses.h" >&5 $as_echo "$as_me: WARNING: could not find a working ncurses/curses.h or ncurses.h" >&2;} fi fi fi # Test for plain Curses (or if CURSES_LIB was set by user) if test "x$with_plaincurses" != xno && test "x$ax_cv_curses_which" = xno; then : if test "x$CURSES_LIB" != x; then : LIBS="$ax_saved_LIBS $CURSES_LIB" else LIBS="$ax_saved_LIBS -lcurses" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Curses library" >&5 $as_echo_n "checking for Curses library... " >&6; } if ${ax_cv_plaincurses+:} false; then : $as_echo_n "(cached) " >&6 else 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 initscr (); int main () { return initscr (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_plaincurses=yes else ax_cv_plaincurses=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_plaincurses" >&5 $as_echo "$ax_cv_plaincurses" >&6; } if test "x$ax_cv_plaincurses" = xyes; then : ax_cv_curses=yes ax_cv_curses_which=plaincurses if test "x$CURSES_LIB" = x; then : CURSES_LIB="-lcurses" fi $as_echo "#define HAVE_CURSES 1" >>confdefs.h # Check for base conformance (and header file) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working curses.h" >&5 $as_echo_n "checking for working curses.h... " >&6; } if ${ax_cv_header_curses_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { chtype a = A_BOLD; int b = KEY_LEFT; initscr(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_header_curses_h=yes else ax_cv_header_curses_h=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_header_curses_h" >&5 $as_echo "$ax_cv_header_curses_h" >&6; } if test "x$ax_cv_header_curses_h" = xyes; then : $as_echo "#define HAVE_CURSES_H 1" >>confdefs.h # Check for X/Open Enhanced conformance { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X/Open Enhanced Curses conformance" >&5 $as_echo_n "checking for X/Open Enhanced Curses conformance... " >&6; } if ${ax_cv_plaincurses_enhanced+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _XOPEN_SOURCE_EXTENDED 1 #include #ifndef _XOPEN_CURSES #error "this Curses library is not enhanced" "this Curses library is not enhanced" #endif int main () { chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; attr_t d = WA_NORMAL; cchar_t e; wint_t f; initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); wattr_set(stdscr, d, 0, NULL); wget_wch(stdscr, &f); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_plaincurses_enhanced=yes else ax_cv_plaincurses_enhanced=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_plaincurses_enhanced" >&5 $as_echo "$ax_cv_plaincurses_enhanced" >&6; } if test "x$ax_cv_plaincurses_enhanced" = xyes; then : ax_cv_curses_enhanced=yes ax_cv_curses_color=yes $as_echo "#define HAVE_CURSES_ENHANCED 1" >>confdefs.h $as_echo "#define HAVE_CURSES_COLOR 1" >>confdefs.h fi # Check for color functions { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Curses color functions" >&5 $as_echo_n "checking for Curses color functions... " >&6; } if ${ax_cv_plaincurses_color+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _XOPEN_SOURCE_EXTENDED 1 #include int main () { chtype a = A_BOLD; int b = KEY_LEFT; chtype c = COLOR_PAIR(1) & A_COLOR; initscr(); init_pair(1, COLOR_WHITE, COLOR_RED); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_plaincurses_color=yes else ax_cv_plaincurses_color=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_plaincurses_color" >&5 $as_echo "$ax_cv_plaincurses_color" >&6; } if test "x$ax_cv_plaincurses_color" = xyes; then : ax_cv_curses_color=yes $as_echo "#define HAVE_CURSES_COLOR 1" >>confdefs.h fi # Check for obsolete functions { $as_echo "$as_me:${as_lineno-$LINENO}: checking for obsolete Curses functions" >&5 $as_echo_n "checking for obsolete Curses functions... " >&6; } if ${ax_cv_plaincurses_obsolete+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { chtype a = A_BOLD; int b = KEY_LEFT; int g = getattrs(stdscr); int h = getcurx(stdscr) + getmaxx(stdscr); initscr(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_plaincurses_obsolete=yes else ax_cv_plaincurses_obsolete=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_plaincurses_obsolete" >&5 $as_echo "$ax_cv_plaincurses_obsolete" >&6; } if test "x$ax_cv_plaincurses_obsolete" = xyes; then : ax_cv_curses_obsolete=yes $as_echo "#define HAVE_CURSES_OBSOLETE 1" >>confdefs.h fi fi if test "x$ax_cv_header_curses_h" = xno; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find a working curses.h" >&5 $as_echo "$as_me: WARNING: could not find a working curses.h" >&2;} fi fi fi if test "x$ax_cv_curses" != xyes; then : ax_cv_curses=no fi if test "x$ax_cv_curses_enhanced" != xyes; then : ax_cv_curses_enhanced=no fi if test "x$ax_cv_curses_color" != xyes; then : ax_cv_curses_color=no fi if test "x$ax_cv_curses_obsolete" != xyes; then : ax_cv_curses_obsolete=no fi LIBS=$ax_saved_LIBS if test "x$ax_cv_curses" != xyes; then as_fn_error $? "requires an X/Open-compatible Curses library with color" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking lib pcre" >&5 $as_echo_n "checking lib pcre... " >&6; } # Check whether --with-pcre was given. if test "${with_pcre+set}" = set; then : withval=$with_pcre; else with_pcre="yes" fi if test ".$with_pcre" = ".no" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } as_fn_error $? "pcre required to build" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: (testing)" >&5 $as_echo "(testing)" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_study in -lpcre" >&5 $as_echo_n "checking for pcre_study in -lpcre... " >&6; } if ${ac_cv_lib_pcre_pcre_study+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcre $LIBS" 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 pcre_study (); int main () { return pcre_study (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcre_pcre_study=yes else ac_cv_lib_pcre_pcre_study=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre_pcre_study" >&5 $as_echo "$ac_cv_lib_pcre_pcre_study" >&6; } if test "x$ac_cv_lib_pcre_pcre_study" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPCRE 1 _ACEOF LIBS="-lpcre $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE in -lpcrecpp" >&5 $as_echo_n "checking for _ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE in -lpcrecpp... " >&6; } if ${ac_cv_lib_pcrecpp__ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcrecpp $LIBS" 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 _ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE (); int main () { return _ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcrecpp__ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE=yes else ac_cv_lib_pcrecpp__ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcrecpp__ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE" >&5 $as_echo "$ac_cv_lib_pcrecpp__ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE" >&6; } if test "x$ac_cv_lib_pcrecpp__ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPCRECPP 1 _ACEOF LIBS="-lpcrecpp $LIBS" fi for ac_header in pcre.h pcre/pcre.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" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done if test "$ac_cv_lib_pcre_pcre_study" = "yes" ; then PCRE_LIBS="-lpcre -lpcrecpp" { $as_echo "$as_me:${as_lineno-$LINENO}: checking lib pcre" >&5 $as_echo_n "checking lib pcre... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PCRE_LIBS" >&5 $as_echo "$PCRE_LIBS" >&6; } else OLDLDFLAGS="$LDFLAGS" ; LDFLAGS="$LDFLAGS -L$with_pcre/lib" OLDCPPFLAGS="$CPPFLAGS" ; CPPFLAGS="$CPPFLAGS -I$with_pcre/include" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_compile in -lpcre" >&5 $as_echo_n "checking for pcre_compile in -lpcre... " >&6; } if ${ac_cv_lib_pcre_pcre_compile+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpcre $LIBS" 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 pcre_compile (); int main () { return pcre_compile (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcre_pcre_compile=yes else ac_cv_lib_pcre_pcre_compile=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre_pcre_compile" >&5 $as_echo "$ac_cv_lib_pcre_pcre_compile" >&6; } if test "x$ac_cv_lib_pcre_pcre_compile" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPCRE 1 _ACEOF LIBS="-lpcre $LIBS" fi CPPFLAGS="$OLDCPPFLAGS" LDFLAGS="$OLDLDFLAGS" if test "$ac_cv_lib_pcre_pcre_compile" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: .setting PCRE_LIBS -L$with_pcre/lib -lpcre" >&5 $as_echo ".setting PCRE_LIBS -L$with_pcre/lib -lpcre" >&6; } PCRE_LDFLAGS="-L$with_pcre/lib" PCRE_LIBS="-lpcre -lpcrecpp" test -d "$with_pcre/include" && PCRE_CFLAGS="-I$with_pcre/include" { $as_echo "$as_me:${as_lineno-$LINENO}: checking lib pcre" >&5 $as_echo_n "checking lib pcre... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PCRE_LIBS" >&5 $as_echo "$PCRE_LIBS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking lib pcre" >&5 $as_echo_n "checking lib pcre... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, (WARNING)" >&5 $as_echo "no, (WARNING)" >&6; } as_fn_error $? "pcre required to build" "$LINENO" 5 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking lib readline" >&5 $as_echo_n "checking lib readline... " >&6; } # Check whether --with-readline was given. if test "${with_readline+set}" = set; then : withval=$with_readline; else with_readline="yes" fi if test ".$with_readline" = ".no" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } as_fn_error $? "readline required to build" "$LINENO" 5 else if test ".$with_readline" = ".yes"; then OLD_LIBS="$LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 $as_echo_n "checking for readline in -lreadline... " >&6; } if ${ac_cv_lib_readline_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline $CURSES_LIB $LIBS" 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_readline=yes else ac_cv_lib_readline_readline=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 $as_echo "$ac_cv_lib_readline_readline" >&6; } if test "x$ac_cv_lib_readline_readline" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBREADLINE 1 _ACEOF LIBS="-lreadline $LIBS" fi LIBS="$OLD_LIBS" if test "$ac_cv_lib_readline_readline" = "yes"; then READLINE_LIBS="-lreadline" { $as_echo "$as_me:${as_lineno-$LINENO}: checking lib readline" >&5 $as_echo_n "checking lib readline... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READLINE_LIBS" >&5 $as_echo "$READLINE_LIBS" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking lib readline" >&5 $as_echo_n "checking lib readline... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, (WARNING)" >&5 $as_echo "no, (WARNING)" >&6; } as_fn_error $? "readline required to build" "$LINENO" 5 fi else LIBS="$LIBS $with_readline/lib/libreadline.a" OLDCPPFLAGS="$CPPFLAGS" ; CPPFLAGS="$CPPFLAGS -I$with_readline/include" 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" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS="$OLDCPPFLAGS" READLINE_LIBS="$with_readline/lib/libreadline.a" test -d "$with_readline/include" && READLINE_CFLAGS="-I$with_readline/include" { $as_echo "$as_me:${as_lineno-$LINENO}: checking lib readline" >&5 $as_echo_n "checking lib readline... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $READLINE_LIBS" >&5 $as_echo "$READLINE_LIBS" >&6; } fi fi # Check whether --with-sqlite3 was given. if test "${with_sqlite3+set}" = set; then : withval=$with_sqlite3; if test "$withval" = "no"; then WANT_SQLITE3="no" elif test "$withval" = "yes"; then WANT_SQLITE3="yes" ac_sqlite3_path="" else WANT_SQLITE3="yes" ac_sqlite3_path="$withval" fi else WANT_SQLITE3="yes" fi SQLITE3_CFLAGS="" SQLITE3_LDFLAGS="" SQLITE3_LIBS="" SQLITE3_VERSION="" if test "x$WANT_SQLITE3" = "xyes"; then ac_sqlite3_header="sqlite3.h" sqlite3_version_req="3.0.0" sqlite3_version_req_shorten=`expr $sqlite3_version_req : '\([0-9]*\.[0-9]*\)'` sqlite3_version_req_major=`expr $sqlite3_version_req : '\([0-9]*\)'` sqlite3_version_req_minor=`expr $sqlite3_version_req : '[0-9]*\.\([0-9]*\)'` sqlite3_version_req_micro=`expr $sqlite3_version_req : '[0-9]*\.[0-9]*\.\([0-9]*\)'` if test "x$sqlite3_version_req_micro" = "x" ; then sqlite3_version_req_micro="0" fi sqlite3_version_req_number=`expr $sqlite3_version_req_major \* 1000000 \ \+ $sqlite3_version_req_minor \* 1000 \ \+ $sqlite3_version_req_micro` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SQLite3 library >= $sqlite3_version_req" >&5 $as_echo_n "checking for SQLite3 library >= $sqlite3_version_req... " >&6; } if test "$ac_sqlite3_path" != ""; then ac_sqlite3_ldflags="-L$ac_sqlite3_path/lib" ac_sqlite3_cppflags="-I$ac_sqlite3_path/include" else for ac_sqlite3_path_tmp in /usr /usr/local /opt ; do if test -f "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header" \ && test -r "$ac_sqlite3_path_tmp/include/$ac_sqlite3_header"; then ac_sqlite3_path=$ac_sqlite3_path_tmp ac_sqlite3_cppflags="-I$ac_sqlite3_path_tmp/include" ac_sqlite3_ldflags="-L$ac_sqlite3_path_tmp/lib" break; fi done fi ac_sqlite3_ldflags="$ac_sqlite3_ldflags" ac_sqlite3_libs="-lsqlite3" saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $ac_sqlite3_cppflags" ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if (SQLITE_VERSION_NUMBER >= $sqlite3_version_req_number) // Everything is okay #else # error SQLite version is too old #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } success="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } succees="no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext 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 CPPFLAGS="$saved_CPPFLAGS" if test "$success" = "yes"; then SQLITE3_CFLAGS="$ac_sqlite3_cppflags" SQLITE3_LDFLAGS="$ac_sqlite3_ldflags" SQLITE3_LIBS="$ac_sqlite3_libs" ac_sqlite3_header_path="$ac_sqlite3_path/include/$ac_sqlite3_header" if test "x$ac_sqlite3_header_path" != "x"; then ac_sqlite3_version=`cat $ac_sqlite3_header_path \ | grep '#define.*SQLITE_VERSION.*\"' | sed -e 's/.* "//' \ | sed -e 's/"//'` if test $ac_sqlite3_version != ""; then SQLITE3_VERSION=$ac_sqlite3_version else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can not find SQLITE_VERSION macro in sqlite3.h header to retrieve SQLite version!" >&5 $as_echo "$as_me: WARNING: Can not find SQLITE_VERSION macro in sqlite3.h header to retrieve SQLite version!" >&2;} fi fi $as_echo "#define HAVE_SQLITE3 /**/" >>confdefs.h fi fi if test x"$SQLITE3_LIBS" = x""; then as_fn_error $? "The sqlite3 developement package must be installed." "$LINENO" 5 fi OLD_LIBS="$LIBS" LIBS="$LIBS ${SQLITE3_LIBS}" ac_fn_c_check_func "$LINENO" "sqlite3_stmt_readonly" "ac_cv_func_sqlite3_stmt_readonly" if test "x$ac_cv_func_sqlite3_stmt_readonly" = xyes; then : $as_echo "#define HAVE_SQLITE3_STMT_READONLY /**/" >>confdefs.h fi LIBS="$OLD_LIBS" case "$host_os" in *) # AC_DEFINE([_XOPEN_SOURCE], [500], [Need pread]) $as_echo "#define _BSD_SOURCE 1" >>confdefs.h ;; esac ALL_LDFLAGS="$LDFLAGS $SQLITE3_LDFLAGS" static_lib_list="libncurses.a libreadline.a libsqlite3.a libz.a libtinfo.a" static_lib_list="$static_lib_list libpcre.a libpcrecpp.a libncursesw.a libbz2.a" static_lib_list="$static_lib_list libgpm.a" # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; fi if test x"${enable_static}" != x"no"; then case "$host_os" in darwin*) STATIC_LDFLAGS="$STATIC_LDFLAGS -Wl,-search_paths_first" ;; esac STATIC_LDFLAGS="$STATIC_LDFLAGS -L`pwd`/src/static-libs" # This is a hack to link against static libraries instead of shared # so that we can build a mostly statically link exe that can # be downloaded and used right away. This is required for OS X and # will, hopefully, make a static binary that is compatible with # many different versions of Linux. mkdir -p src/static-libs rm -f src/static-libs/*.a for libflag in $ALL_LDFLAGS; do case $libflag in -Lstatic-libs) ;; -L*) libdir=`echo $libflag | sed -e 's/-L//'` for slib in $static_lib_list; do if test -e "$libdir/$slib"; then ln -sf "$libdir/$slib" src/static-libs/. fi done ;; esac done fi ac_config_headers="$ac_config_headers src/config.h" ac_config_files="$ac_config_files Makefile" ac_config_files="$ac_config_files TESTS_ENVIRONMENT" ac_config_files="$ac_config_files src/Makefile" ac_config_files="$ac_config_files test/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 if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi 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= U= 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= 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__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCXX\" 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 : "${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. as_myself= 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 STATUS 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=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&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 -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' 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 # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # 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 lnav $as_me 0.7.0, which was generated by GNU Autoconf 2.69. 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="\\ lnav config.status 0.7.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 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=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= 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"` ;; '') as_fn_error $? "missing file argument" ;; 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 "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "src/config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/config.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "TESTS_ENVIRONMENT") CONFIG_FILES="$CONFIG_FILES TESTS_ENVIRONMENT" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/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= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_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 -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # 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 {' >"$ac_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 >>"\$ac_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 >>"\$ac_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 < "$ac_tmp/subs1.awk" > "$ac_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 sole $(srcdir), # ${srcdir} and @srcdir@ entries 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[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// 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 >"$ac_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_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; 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="$ac_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 1 "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 >"$ac_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 "$ac_tmp/subs.awk" \ >$ac_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' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_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 "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_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 "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_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 "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_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"" || { # Older Autoconf 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"` # 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'`; 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 1 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 lnav-0.7.0/configure.ac000664 000765 000024 00000010522 12313323136 015213 0ustar00stackstaff000000 000000 AC_INIT(lnav, 0.7.0, lnav@googlegroups.com) AC_CONFIG_SRCDIR([src/lnav.cc]) AM_INIT_AUTOMAKE([foreign subdir-objects]) AM_SILENT_RULES([yes]) AC_PREFIX_DEFAULT(/usr) AC_CANONICAL_HOST for defdir in /opt/local /usr/local /usr /; do if test -d "$defdir/include"; then CPPFLAGS="$CPPFLAGS -I$defdir/include" fi if test -d "$defdir/lib"; then LDFLAGS="$LDFLAGS -L$defdir/lib" fi if test -d "$defdir/lib64"; then LDFLAGS="$LDFLAGS -L$defdir/lib64" fi if test -d "$defdir/lib/x86_64-linux-gnu"; then LDFLAGS="$LDFLAGS -L$defdir/lib/x86_64-linux-gnu" fi done dnl abssrcdir is the absolute path to the source base (regardless of where dnl you are building it) case x$srcdir in x/*) abssrcdir=$srcdir ;; *) abssrcdir=`pwd`/$srcdir ;; esac AC_SUBST(abssrcdir) AC_PROG_CXX CPPFLAGS="$CPPFLAGS -D_ISOC99_SOURCE -D__STDC_LIMIT_MACROS" # CFLAGS=`echo $CFLAGS | sed 's/-O2//g'` # CXXFLAGS=`echo $CXXFLAGS | sed 's/-O2//g'` AC_ARG_ENABLE([profiling], AS_HELP_STRING([--enable-profiling], [Compile with gprof(1) profiling support])) AC_MSG_CHECKING(gprof(4) profiling support) if test x"${enable_profiling}" = x"yes" ; then CFLAGS="$CFLAGS -pg -gstabs" CXXFLAGS="$CXXFLAGS -pg -gstabs" LDFLAGS="$LDFLAGS -pg" else enable_profiling=no fi AC_MSG_RESULT($enable_profiling) AC_SUBST(CFLAGS_PG) AC_PROG_INSTALL AC_PROG_RANLIB AC_PROG_LN_S AC_PROG_MAKE_SET AM_PATH_PYTHON([2.4]) AC_PATH_PROG(SQLITE3_CMD, [sqlite3]) if test x"$SQLITE3_CMD" = x""; then AC_MSG_ERROR([The sqlite3 command is required]) fi AC_PATH_PROG(BZIP2_CMD, [bzip2]) AC_CHECK_SIZEOF(off_t) AC_CHECK_SIZEOF(size_t) AC_STRUCT_TIMEZONE AC_SEARCH_LIBS(openpty, util) AC_SEARCH_LIBS(gzseek, z, [], [AC_MSG_ERROR([libz required to build])]) AC_SEARCH_LIBS(BZ2_bzopen, bz2) AC_SEARCH_LIBS(dlopen, dl) AC_SEARCH_LIBS(backtrace, execinfo) # Sometimes, curses depends on these libraries being linked in... AC_SEARCH_LIBS(cur_term, tinfo) AC_SEARCH_LIBS(Gpm_Open, gpm) AC_CHECK_HEADERS(execinfo.h pty.h util.h zlib.h bzlib.h libutil.h sys/ttydefaults.h) AX_WITH_CURSES if test "x$ax_cv_curses" != xyes; then AC_MSG_ERROR([requires an X/Open-compatible Curses library with color]) fi AX_PATH_LIB_PCRE([], [AC_MSG_ERROR([pcre required to build])]) AX_PATH_LIB_READLINE([], [AC_MSG_ERROR([readline required to build])]) AX_LIB_SQLITE3("3.0.0") if test x"$SQLITE3_LIBS" = x""; then AC_MSG_ERROR([The sqlite3 developement package must be installed.]) fi OLD_LIBS="$LIBS" LIBS="$LIBS ${SQLITE3_LIBS}" AC_CHECK_FUNC(sqlite3_stmt_readonly, AC_DEFINE([HAVE_SQLITE3_STMT_READONLY], [], [Have the sqlite3_stmt_readonly function])) LIBS="$OLD_LIBS" case "$host_os" in *) # AC_DEFINE([_XOPEN_SOURCE], [500], [Need pread]) AC_DEFINE([_BSD_SOURCE], [1], [Need pread]) ;; esac ALL_LDFLAGS="$LDFLAGS $SQLITE3_LDFLAGS" static_lib_list="libncurses.a libreadline.a libsqlite3.a libz.a libtinfo.a" static_lib_list="$static_lib_list libpcre.a libpcrecpp.a libncursesw.a libbz2.a" static_lib_list="$static_lib_list libgpm.a" AC_ARG_ENABLE([static], AS_HELP_STRING([--disable-static], [Disable static linking])) if test x"${enable_static}" != x"no"; then case "$host_os" in darwin*) STATIC_LDFLAGS="$STATIC_LDFLAGS -Wl,-search_paths_first" ;; esac STATIC_LDFLAGS="$STATIC_LDFLAGS -L`pwd`/src/static-libs" # This is a hack to link against static libraries instead of shared # so that we can build a mostly statically link exe that can # be downloaded and used right away. This is required for OS X and # will, hopefully, make a static binary that is compatible with # many different versions of Linux. mkdir -p src/static-libs rm -f src/static-libs/*.a for libflag in $ALL_LDFLAGS; do case $libflag in -Lstatic-libs) ;; -L*) libdir=`echo $libflag | sed -e 's/-L//'` for slib in $static_lib_list; do if test -e "$libdir/$slib"; then ln -sf "$libdir/$slib" src/static-libs/. fi done ;; esac done fi AC_SUBST(STATIC_LDFLAGS) AC_CONFIG_HEADERS([src/config.h]) AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([TESTS_ENVIRONMENT]) AC_CONFIG_FILES([src/Makefile]) AC_CONFIG_FILES([test/Makefile]) AC_OUTPUT lnav-0.7.0/depcomp000775 000765 000024 00000027533 12211635053 014315 0ustar00stackstaff000000 000000 #! /bin/sh # depcomp - compile a program generating dependencies as side-effects # Copyright 1999, 2000 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 . 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 # `libtool' can also be set to `yes' or `no'. if test -z "$depfile"; then base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` dir=`echo "$object" | sed 's,/.*$,/,'` if test "$dir" = "$object"; then dir= fi # FIXME: should be _deps on DOS. depfile="$dir.deps/$base" fi 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. 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. stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" outname="$stripped.o" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then # 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" ;; 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 tmpdepfile1="$dir.libs/$base.lo.d" tmpdepfile2="$dir.libs/$base.d" "$@" -Wc,-MD else tmpdepfile1="$dir$base.o.d" tmpdepfile2="$dir$base.d" "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi if test -f "$tmpdepfile1"; then tmpdepfile="$tmpdepfile1" else tmpdepfile="$tmpdepfile2" fi if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a space and a tab 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 proprocessed 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'. We will use -o /dev/null later, # however we can't do the remplacement now because # `-o $object' might simply not be used 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 "$@" -o /dev/null $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 $? # 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 ;; -*) ;; *) 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 proprocessed 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 proprocessed 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 lnav-0.7.0/INSTALL000664 000765 000024 00000022024 12211635053 013757 0ustar00stackstaff000000 000000 Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. (Caching is disabled by default to prevent problems with accidental use of stale cache files.) If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You only need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not support the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PATH'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PATH', the package will use PATH as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=PATH' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the `--target=TYPE' option to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc will cause the specified gcc to be used as the C compiler (unless it is overridden in the site shell script). `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. lnav-0.7.0/install-sh000775 000765 000024 00000012701 12211635053 014733 0ustar00stackstaff000000 000000 #!/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 : fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=$mkdirprog 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" ] || [ -d "$src" ] then : else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else : 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 : 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 : fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; 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 : 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 :;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 lnav-0.7.0/LICENSE000664 000765 000024 00000002450 12211635053 013734 0ustar00stackstaff000000 000000 Copyright (c) 2010, Timothy Stack All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. lnav-0.7.0/lnav.1000664 000765 000024 00000005032 12276172454 013764 0ustar00stackstaff000000 000000 .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.43.3. .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .\" Define macros .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .TH LNAV "1" "August 2013" .SH NAME lnav \- ncurses-based log file viewer .SH SYNOPSIS .B lnav [\-hVsar] [logfile1 logfile2 ...] .SH DESCRIPTION The log file navigator, lnav, is an enhanced log file viewer that takes advantage of any semantic information that can be gleaned from the files being viewed, such as timestamps and log levels. Using this extra semantic information, lnav can do things like interleaving messages from different files, generate histograms of messages over time, and providing hotkeys for navigating through the file. It is hoped that these features will allow the user to quickly and efficiently zero in on problems. .SH KEY BINDINGS .TP ? View/leave the online help text. .TP q Quit the program. .SH OPTIONS .TP \fB\-h\fR Print help and exit .TP \fB\-H\fR Display the internal help text. .TP \fB\-d\fR file Write debug messages to the given file. .TP \fB\-V\fR Print version information. .TP \fB\-s\fR Load the most recent syslog messages file. .TP \fB\-a\fR Load all of the most recent log file types. .TP \fB\-r\fR Load older rotated log files as well. .TP \fB\-t\fR Prepend timestamps to the lines of data being read in on the standard input. .TP \fB\-w\fR file Write the contents of the standard input to this file. .SS "Optional arguments:" .TP logfile1 The log files or directories to view. If a directory is given, all of the files in the directory will be loaded. .SH EXAMPLES To load and follow the syslog file: .PP .Vb 1 \& lnav \-s .Ve .PP To load all of the files in /var/log: .PP .Vb 1 \& lnav /var/log .Ve .PP To watch the output of make with timestamps prepended: .PP .Vb 1 \& make 2>&1 | lnav \-t .Ve .SH AUTHOR This manual page was written by Salvatore Bonaccorso for the Debian system (but may be used by others). lnav-0.7.0/lnav.m4000664 000765 000024 00000005044 12231753152 014136 0ustar00stackstaff000000 000000 AC_DEFUN([AX_PATH_LIB_PCRE],[dnl AC_MSG_CHECKING([lib pcre]) AC_ARG_WITH(pcre, [ --with-pcre[[=prefix]]],, with_pcre="yes") if test ".$with_pcre" = ".no" ; then AC_MSG_RESULT([disabled]) m4_ifval($2,$2) else AC_MSG_RESULT([(testing)]) AC_CHECK_LIB(pcre, pcre_study) AC_CHECK_LIB(pcrecpp, _ZN7pcrecpp2RE4InitERKSsPKNS_10RE_OptionsE) AC_CHECK_HEADERS(pcre.h pcre/pcre.h) if test "$ac_cv_lib_pcre_pcre_study" = "yes" ; then PCRE_LIBS="-lpcre -lpcrecpp" AC_MSG_CHECKING([lib pcre]) AC_MSG_RESULT([$PCRE_LIBS]) m4_ifval($1,$1) else OLDLDFLAGS="$LDFLAGS" ; LDFLAGS="$LDFLAGS -L$with_pcre/lib" OLDCPPFLAGS="$CPPFLAGS" ; CPPFLAGS="$CPPFLAGS -I$with_pcre/include" AC_CHECK_LIB(pcre, pcre_compile) CPPFLAGS="$OLDCPPFLAGS" LDFLAGS="$OLDLDFLAGS" if test "$ac_cv_lib_pcre_pcre_compile" = "yes" ; then AC_MSG_RESULT(.setting PCRE_LIBS -L$with_pcre/lib -lpcre) PCRE_LDFLAGS="-L$with_pcre/lib" PCRE_LIBS="-lpcre -lpcrecpp" test -d "$with_pcre/include" && PCRE_CFLAGS="-I$with_pcre/include" AC_MSG_CHECKING([lib pcre]) AC_MSG_RESULT([$PCRE_LIBS]) m4_ifval($1,$1) else AC_MSG_CHECKING([lib pcre]) AC_MSG_RESULT([no, (WARNING)]) m4_ifval($2,$2) fi fi fi AC_SUBST([PCRE_LIBS]) AC_SUBST([PCRE_CFLAGS]) ]) AC_DEFUN([AX_PATH_LIB_READLINE],[dnl AC_MSG_CHECKING([lib readline]) AC_ARG_WITH(readline, [ --with-readline[[=prefix]] compile xmlreadline part (via libreadline check)],, with_readline="yes") if test ".$with_readline" = ".no" ; then AC_MSG_RESULT([disabled]) m4_ifval($2,$2) else if test ".$with_readline" = ".yes"; then OLD_LIBS="$LIBS" AC_CHECK_LIB(readline, readline, [], [], [$CURSES_LIB]) LIBS="$OLD_LIBS" if test "$ac_cv_lib_readline_readline" = "yes"; then READLINE_LIBS="-lreadline" AC_MSG_CHECKING([lib readline]) AC_MSG_RESULT([$READLINE_LIBS]) m4_ifval($1,$1) else AC_MSG_CHECKING([lib readline]) AC_MSG_RESULT([no, (WARNING)]) m4_ifval($2,$2) fi else LIBS="$LIBS $with_readline/lib/libreadline.a" OLDCPPFLAGS="$CPPFLAGS" ; CPPFLAGS="$CPPFLAGS -I$with_readline/include" AC_CHECK_HEADERS(readline.h readline/readline.h) CPPFLAGS="$OLDCPPFLAGS" READLINE_LIBS="$with_readline/lib/libreadline.a" test -d "$with_readline/include" && READLINE_CFLAGS="-I$with_readline/include" AC_MSG_CHECKING([lib readline]) AC_MSG_RESULT([$READLINE_LIBS]) m4_ifval($1,$1) fi fi AC_SUBST([READLINE_LIBS]) AC_SUBST([READLINE_CFLAGS]) ]) lnav-0.7.0/Makefile.am000664 000765 000024 00000000234 12312755466 014776 0ustar00stackstaff000000 000000 ACLOCAL_AMFLAGS = -I . SUBDIRS = src test noinst_SCRIPTS = TESTS_ENVIRONMENT dist_man_MANS = lnav.1 EXTRA_DIST = \ AUTHORS \ LICENSE \ README.md lnav-0.7.0/Makefile.in000664 000765 000024 00000067016 12313323142 015001 0ustar00stackstaff000000 000000 # Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) mkinstalldirs \ $(srcdir)/TESTS_ENVIRONMENT.in $(dist_man_MANS) AUTHORS \ INSTALL NEWS README compile config.guess config.sub depcomp \ install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/ax_sqlite3.m4 \ $(top_srcdir)/ax_with_curses.m4 $(top_srcdir)/lnav.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 = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = TESTS_ENVIRONMENT CONFIG_CLEAN_VPATH_FILES = SCRIPTS = $(noinst_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-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 \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" NROFF = nroff MANS = $(dist_man_MANS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_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 DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BZIP2_CMD = @BZIP2_CMD@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CFLAGS_PG = @CFLAGS_PG@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CURSES_LIB = @CURSES_LIB@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ 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@ 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@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ READLINE_CFLAGS = @READLINE_CFLAGS@ READLINE_LIBS = @READLINE_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_CMD = @SQLITE3_CMD@ SQLITE3_LDFLAGS = @SQLITE3_LDFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ SQLITE3_VERSION = @SQLITE3_VERSION@ STATIC_LDFLAGS = @STATIC_LDFLAGS@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ abssrcdir = @abssrcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ 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@ ACLOCAL_AMFLAGS = -I . SUBDIRS = src test noinst_SCRIPTS = TESTS_ENVIRONMENT dist_man_MANS = lnav.1 EXTRA_DIST = \ AUTHORS \ LICENSE \ README.md all: all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign 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: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): TESTS_ENVIRONMENT: $(top_builddir)/config.status $(srcdir)/TESTS_ENVIRONMENT.in cd $(top_builddir) && $(SHELL) ./config.status $@ install-man1: $(dist_man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(dist_man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) # 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. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) 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; \ $(am__define_uniq_tagged_files); \ 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-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files 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 \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -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__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_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) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(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) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(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" \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(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__post_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: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { 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 $(SCRIPTS) $(MANS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(man1dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: 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-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-man 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-man1 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 mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-man uninstall-man: uninstall-man1 .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ distcheck distclean distclean-generic 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-man1 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-man uninstall-man1 # 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: lnav-0.7.0/missing000775 000765 000024 00000015331 12211635053 014330 0ustar00stackstaff000000 000000 #! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2012-06-26.16; # UTC # Copyright (C) 1996-2013 Free Software Foundation, Inc. # Originally written 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, see . # 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 case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'automa4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: lnav-0.7.0/mkinstalldirs000775 000765 000024 00000003411 12211635053 015533 0ustar00stackstaff000000 000000 #! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain errstatus=0 dirmode="" usage="\ Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." # process command line arguments while test $# -gt 0 ; do case "${1}" in -h | --help | --h* ) # -h for help echo "${usage}" 1>&2; exit 0 ;; -m ) # -m PERM arg shift test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } dirmode="${1}" shift ;; -- ) shift; break ;; # stop option processing -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option * ) break ;; # first non-opt arg esac done for file do if test -d "$file"; then shift else break fi done case $# in 0) exit 0 ;; esac case $dirmode in '') if mkdir -p -- . 2>/dev/null; then echo "mkdir -p -- $*" exec mkdir -p -- "$@" fi ;; *) if mkdir -m "$dirmode" -p -- . 2>/dev/null; then echo "mkdir -m $dirmode -p -- $*" exec mkdir -m "$dirmode" -p -- "$@" fi ;; esac for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr else if test ! -z "$dirmode"; then echo "chmod $dirmode $pathcomp" lasterr="" chmod "$dirmode" "$pathcomp" || lasterr=$? if test ! -z "$lasterr"; then errstatus=$lasterr fi fi fi fi pathcomp="$pathcomp/" done done exit $errstatus # Local Variables: # mode: shell-script # sh-indentation: 3 # End: # mkinstalldirs ends here lnav-0.7.0/NEWS000664 000765 000024 00000012373 12313207221 013426 0ustar00stackstaff000000 000000 lnav v0.7.0: Features: * Add the '.schema' SQL command to open a view that displays the schema for the internal tables and any attached databases. If lnav was only executed with a SQLite database and no text files, this view will open by default. * The scroll bar now indicates the location of errors/warnings, search hits, and bookmarks. * The xterm title is update to reflect the file name for the top line in the view. * Added a "headless" mode so that you can execute commands and run SQL queries from the command-line without having to do it from the curses UI. * When doing a search or SQL query, any text that is currently being displayed can be tab-completed. * The '-H' option was added so you can view the internal help text. * Added the 'g/G' hotkeys to move to the top/bottom of the file. * Added a 'log_mark' column to the log tables that indicates whether or not a log message is bookmarked. The field is writable, so you can bookmark lines using an SQL UPDATE query. * Added syntax-highlighting when editing SQL queries or search regexes. * Added a "write-json-to" command that writes the result of a SQL query to a JSON-formatted file. * The "elapsed time" column now uses red/green coloring to indicate sharp changes in the message rate. * Added a "set-min-log-level" command to filter out log messages that are below a given level. Fixes: * Performance improvements. * Multi-line filtering has been fixed. * A collator has been added to the log_level column in the log tables so that you can write expressions like "log_level > 'warning'". * The log_time datetime format now matches what is returned by "datetime('now')" so that collating works correctly. * If a search string is not valid PCRE syntax, a search is done for the exact string instead of just returning an error. * Static-linking has been cleaned up. * OpenSSL is no longer a requirement. * Alpha support for Windows/cygwin. * Environment variables can now be accessed in SQL queries using the syntax: $VAR_NAME * An internal log is kept and written out on a crash. * Partition bookmarks are now tracked separately from regular user bookmarks. You can start a partition with the 'partition-name' command and remove it with the 'clear-partition' command. * Improved display of possible matches during tab-completion in the command-prompt. The matches are now shown in a separate view and pressing tab repeatedly will scroll through the view. * The "open" command now does shell word expansion for file names. * More config directory paths have been added: /etc/lnav, $prefix/etc/lnav, and directories passed on the command-line with -I. lnav v0.6.2: Features: * Word-wrap support. Fixes: * Fix some OS X Mavericks build/runtime issues. lnav v0.6.1: Features: * Support for JSON-encoded log files. Fixes: * Some minor fixes and performance improvements. lnav v0.6.0: Features: * Custom log formats and more builtin formats * Automatic extraction of data from logs * UI improvements, support for 256 color terminals lnav v0.5.1: Features: * Added the '-t' and '-w' options which can be used to prepend a timestamp to any data piped in on stdin and to specify a file to write the contents of stdin to. Fixes: * Cleanup for packaging. lnav v0.5.0: Features: * Files can be specified on the command-line using wildcards so that new files are automatically loaded. Directories can also be passed as command-line arguments to read all of the files in the directory. * Builds on cygwin again. * Added the 'C' hotkey to clear any existing user bookmarks. * Added experimental support for accepting input from mice. Fixes: * Internal cleanup. * Copying to the clipboard on OS X is now supported. * Many bug fixes. lnav v0.4.0: Features: * Files that are not recognized as containing log messages have been broken out to a separate text files view. You can flip between the log view and the text file view with the 't' hotkey. When viewing text files, the 'f' hotkey will switch between files. * Files compressed with bzip2 are recognized and decompressed on the fly. * Added a "session" file and command for storing commands that should be executed on startup. For example, if you always want some highlighting to be done, you can add that command to the session file. Fixes: * Add some more log file formats for generic log files. * Performance improvements for compressed files. * Works on OS X now. lnav v0.3.0: Changes: * The hotkey for the SQL view was changed to 'v' and 'V' from '.'. Features: * You can now switch between the SQL result view and the log view while keeping the top of the views in sync with the "line_number" column. Fixes: * The "line_number" column is no longer included in the SQL result view's stacked bar graph. * Added a "warnings" count to the histogram view. lnav-0.7.0/README000664 000765 000024 00000002444 12274203105 013610 0ustar00stackstaff000000 000000 LNAV ---- The log file navigator, lnav, is an enhanced log file viewer that takes advantage of any semantic information that can be gleaned from the files being viewed, such as timestamps and log levels. Using this extra semantic information, lnav can do things like interleaving messages from different files, generate histograms of messages over time, and providing hotkeys for navigating through the file. It is hoped that these features will allow the user to quickly and efficiently zero in on problems. PREREQUISITES ------------- Lnav requires the following software packages: libpcre - The Perl Compatible Regular Expression (PCRE) library. sqlite - The SQLite database engine. ncurses - The ncurses text UI library. readline - The readline line editing library. zlib - The zlib compression library. bz2 - The bzip2 compression library. INSTALLATION ------------ Lnav follows the usual GNU style for configuring and installing software: $ ./configure $ make $ sudo make install USING ----- The only file installed is the executable, "lnav". You can execute it with no arguments to view the default set of files: $ lnav You can view all the syslog messages by running: $ lnav /var/log/messages* SEE ALSO -------- Lnav website: http://lnav.org lnav-0.7.0/README.md000664 000765 000024 00000003554 12211635053 014214 0ustar00stackstaff000000 000000 [![Build Status](https://travis-ci.org/tstack/lnav.png)](https://travis-ci.org/tstack/lnav) _This is the source repository for **lnav**, visit [http://lnav.org](http://lnav.org) for a high level overview._ LNAV -- The Logfile Navigator ============================= The log file navigator, lnav, is an enhanced log file viewer that takes advantage of any semantic information that can be gleaned from the files being viewed, such as timestamps and log levels. Using this extra semantic information, lnav can do things like interleaving messages from different files, generate histograms of messages over time, and providing hotkeys for navigating through the file. It is hoped that these features will allow the user to quickly and efficiently zero in on problems. Prerequisites ------------- Lnav requires the following software packages: * libpcre - The Perl Compatible Regular Expression (PCRE) library. * sqlite - The SQLite database engine. * ncurses - The ncurses text UI library. * readline - The readline line editing library. * zlib - The zlib compression library. * bz2 - The bzip2 compression library. Installation ------------ Lnav follows the usual GNU style for configuring and installing software: $ ./configure $ make $ sudo make install Using ----- The only file installed is the executable, "lnav". You can execute it with no arguments to view the default set of files: $ lnav You can view all the syslog messages by running: $ lnav /var/log/messages* Screenshot ---------- The following screenshot shows a syslog file. Log lines are displayed with highlights. Errors are red and warnings are yellow. [![Screenshot](http://tstack.github.io/lnav/lnav-syslog-thumb.png)](http://tstack.github.io/lnav/lnav-syslog.png) See Also -------- The lnav website can be found at: > [http://lnav.org](http://lnav.org) lnav-0.7.0/src/000775 000765 000024 00000000000 12315725122 013517 5ustar00stackstaff000000 000000 lnav-0.7.0/test/000775 000765 000024 00000000000 12315725123 013710 5ustar00stackstaff000000 000000 lnav-0.7.0/test-driver000775 000765 000024 00000007611 12211635054 015132 0ustar00stackstaff000000 000000 #! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2012-06-27.10; # UTC # Copyright (C) 2011-2013 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, see . # 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. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then estatus=1 fi case $estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # 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-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: lnav-0.7.0/TESTS_ENVIRONMENT.in000664 000765 000024 00000005022 12311035743 016044 0ustar00stackstaff000000 000000 #! /bin/bash top_srcdir="@abssrcdir@" export top_srcdir srcdir="@abssrcdir@/test" export srcdir # The top build directory, derived from the path to this script. top_builddir=`dirname $0` export top_builddir test_dir="@abssrcdir@/test" export test_dir BZIP2_CMD="@BZIP2_CMD@" export BZIP2_CMD # The full path of the test case test_file=$1 # The base name of the test case test_file_base=`basename $1` # The current test number for shell based tests. test_num=0 ## BEGIN Functions LAST_TEST="" # # Run a test case and capture its standard out and standard err. # # Usage: run_test [ ...] # # Example: # # To run rktimes and capture all of its stdio output: # # run_test rktimes -V # run_test() { LAST_TEST="test: $@" "$@" > ${test_file_base}_${test_num}.tmp 2> ${test_file_base}_${test_num}.err } # # Check the output generated by a run_test() call. # # Usage: check_output {Expected output on stdin} # # Example: # # To check the output of 'rktimes -V' and print out 'Unable to get version?' # if the output doesn't match: # # run_test rktimes -V # check_output "Unable to get version?" < ${test_file_base}_${test_num}.diff if test $? -ne 0; then echo $LAST_TEST echo $1 cat ${test_file_base}_${test_num}.diff exit 1 fi test_num=`expr ${test_num} \+ 1` } check_error_output() { diff -u ${test_file_base}_${test_num}.err - \ > ${test_file_base}_${test_num}.err.diff if test $? -ne 0; then echo $LAST_TEST echo $1 cat ${test_file_base}_${test_num}.err.diff exit 1 fi } # # Grep for a string in the output generated by a run_test() call. # # Usage: grep_output_for # # Example: # # To check the output of 'cbhey -l' for 'IDL:Foobar:1.0' and print out # 'Unable to list supported interfaces?' if it is not found: # # run_test cbhey -l # grep_output_for "IDL:Foobar:1.0" "Unable to list supported interface?" # grep_output_for() { if grep -q $1 ${test_file_base}_${test_num}.tmp > /dev/null 2>&1; then : else echo "${test_file_base}_${test_num}.tmp: $2" exit 1 fi test_num=`expr ${test_num} \+ 1` } on_error_fail_with() { if test $? -ne 0; then echo $1 > /dev/stderr exit 1 fi } ## END Functions # Finally, run the test... if test -x $1 && test `basename $1 .sh` == `basename $1`; then exec $* else # Shell script shift . ${test_file} fi lnav-0.7.0/test/ansi-colors.0.in000664 000765 000024 00000005215 12211635054 016630 0ustar00stackstaff000000 000000 Basic ANSI colors (eight-color, or dim) black  black  red  green  yellow  blue  magenta cyan  white  bold black  black  red  green  yellow  blue  magenta cyan  white  red  black  red  green  yellow  blue  magenta cyan  white  bold red  black  red  green  yellow  blue  magenta cyan  white  green  black  red  green  yellow  blue  magenta cyan  white  bold green  black  red  green  yellow  blue  magenta cyan  white  yellow  black  red  green  yellow  blue  magenta cyan  white  bold yellow  black  red  green  yellow  blue  magenta cyan  white  blue  black  red  green  yellow  blue  magenta cyan  white  bold blue  black  red  green  yellow  blue  magenta cyan  white  magenta  black  red  green  yellow  blue  magenta cyan  white  bold magenta  black  red  green  yellow  blue  magenta cyan  white  cyan  black  red  green  yellow  blue  magenta cyan  white  bold cyan  black  red  green  yellow  blue  magenta cyan  white  white  black  red  green  yellow  blue  magenta cyan  white  bold white  black  red  green  yellow  blue  magenta cyan  white  Attributes: bold dark italic underline blink concealed  testing  testing  testing  testing  testing  testing  lnav-0.7.0/test/datafile_simple.0000664 000765 000024 00000001000 12211635054 017100 0ustar00stackstaff000000 000000 a=1 b=2 c=3,4 key 0:1 ^ a num 2:3 ^ 1 val 2:3 ^ 1 pair 0:3 ^-^ a=1 key 4:5 ^ b num 6:7 ^ 2 val 6:7 ^ 2 pair 4:7 ^-^ b=2 key 8:9 ^ c num 10:11 ^ 3 val 10:11 ^ 3 pair 8:11 ^-^ c=3 key 12:12 ^ num 12:13 ^ 4 val 12:13 ^ 4 pair 12:13 ^ 4 lnav-0.7.0/test/datafile_simple.1000664 000765 000024 00000000437 12211635054 017116 0ustar00stackstaff000000 000000 current speed: 38 mph key 0:0 key 0:13 ^-----------^ current speed pair 0:13 ^-----------^ current speed key 15:15 ^ num 15:17 ^^ 38 pair 15:17 ^^ 38 lnav-0.7.0/test/datafile_simple.10000664 000765 000024 00000000276 12307146044 017201 0ustar00stackstaff000000 000000 quoted string u'pm/runtime' key 16:16 ^ quot 16:26 ^--------^ pm/runtime pair 16:26 ^--------^ pm/runtime lnav-0.7.0/test/datafile_simple.11000664 000765 000024 00000000537 12307351512 017200 0ustar00stackstaff000000 000000 version numbers 0.6.16 1.2-a1 key 17:17 ^ vers 17:23 ^----^ 0.6.16 pair 17:23 ^----^ 0.6.16 key 25:25 ^ vers 25:31 ^----^ 1.2-a1 pair 25:31 ^----^ 1.2-a1 lnav-0.7.0/test/datafile_simple.2000664 000765 000024 00000001774 12211635054 017124 0ustar00stackstaff000000 000000 1,2,3,4,five,six,7 key 0:0 num 0:1 ^ 1 val 0:1 ^ 1 pair 0:1 ^ 1 key 2:2 ^ num 2:3 ^ 2 val 2:3 ^ 2 pair 2:3 ^ 2 key 4:4 ^ num 4:5 ^ 3 val 4:5 ^ 3 pair 4:5 ^ 3 key 6:6 ^ num 6:7 ^ 4 val 6:7 ^ 4 pair 6:7 ^ 4 key 8:8 ^ word 8:12 ^--^ five val 8:12 ^--^ five pair 8:12 ^--^ five key 13:13 ^ word 13:16 ^-^ six val 13:16 ^-^ six pair 13:16 ^-^ six key 17:17 ^ num 17:18 ^ 7 val 17:18 ^ 7 pair 17:18 ^ 7 lnav-0.7.0/test/datafile_simple.3000664 000765 000024 00000001050 12211635054 017110 0ustar00stackstaff000000 000000 1 2 3 4 five six 7 key 0:0 num 0:1 ^ 1 pair 0:1 ^ 1 key 2:2 ^ num 2:3 ^ 2 pair 2:3 ^ 2 key 4:4 ^ num 4:5 ^ 3 pair 4:5 ^ 3 key 6:6 ^ num 6:7 ^ 4 pair 6:7 ^ 4 key 17:17 ^ num 17:18 ^ 7 pair 17:18 ^ 7 lnav-0.7.0/test/datafile_simple.4000664 000765 000024 00000000414 12211635054 017114 0ustar00stackstaff000000 000000 the-value: "Hello, World!" key 0:9 ^-------^ the-value quot 12:25 ^-----------^ Hello, World! val 12:25 ^-----------^ Hello, World! pair 0:25 ^-----------------------^ the-value: "Hello, World! lnav-0.7.0/test/datafile_simple.5000664 000765 000024 00000000645 12211635054 017123 0ustar00stackstaff000000 000000 this is a url: http://www.example.com/foo-bar key 0:13 ^-----------^ this is a url url 15:45 ^----------------------------^ http://www.example.com/foo-bar val 15:45 ^----------------------------^ http://www.example.com/foo-bar pair 0:45 ^-------------------------------------------^ this is a url: http://www.example.com/foo-bar lnav-0.7.0/test/datafile_simple.6000664 000765 000024 00000001424 12211635054 017120 0ustar00stackstaff000000 000000 qualified:name: foo=1 bar=2 key 0:0 word 0:9 ^-------^ qualified val 0:9 ^-------^ qualified pair 0:9 ^-------^ qualified key 10:10 ^ word 10:14 ^--^ name val 10:14 ^--^ name pair 10:14 ^--^ name key 16:19 ^-^ foo num 20:21 ^ 1 val 20:21 ^ 1 pair 16:21 ^---^ foo=1 key 22:25 ^-^ bar num 26:27 ^ 2 val 26:27 ^ 2 pair 22:27 ^---^ bar=2 lnav-0.7.0/test/datafile_simple.7000664 000765 000024 00000001032 12211635054 017114 0ustar00stackstaff000000 000000 func(arg1="a", arg2="b") key 5:5 ^ key 5:9 ^--^ arg1 quot 11:12 ^ a val 11:12 ^ a pair 5:12 ^-----^ arg1="a key 15:19 ^--^ arg2 quot 21:22 ^ b val 21:22 ^ b pair 15:22 ^-----^ arg2="b grp 5:22 ^---------------^ arg1="a", arg2="b pair 5:22 ^---------------^ arg1="a", arg2="b lnav-0.7.0/test/datafile_simple.8000664 000765 000024 00000014071 12211635054 017124 0ustar00stackstaff000000 000000 Succeeded authorizing right 'system.privilege.taskport.debug' by client '/usr/libexec/taskgated' [76339] for authorization created by '/usr/libexec/taskgated' [77395] (100003,1) key 29:29 ^ quot 29:60 ^-----------------------------^ system.privilege.taskport.debug pair 29:60 ^-----------------------------^ system.privilege.taskport.debug key 73:73 ^ quot 73:95 ^--------------------^ /usr/libexec/taskgated pair 73:95 ^--------------------^ /usr/libexec/taskgated key 98:98 ^ key 98:98 ^ num 98:103 ^---^ 76339 pair 98:103 ^---^ 76339 grp 98:103 ^---^ 76339 pair 98:103 ^---^ 76339 key 135:135 ^ quot 135:157 ^--------------------^ /usr/libexec/taskgated pair 135:157 ^--------------------^ /usr/libexec/taskgated key 160:160 ^ key 160:160 ^ num 160:165 ^---^ 77395 pair 160:165 ^---^ 77395 grp 160:165 ^---^ 77395 pair 160:165 ^---^ 77395 key 168:168 ^ key 168:168 ^ num 168:174 ^----^ 100003 pair 168:174 ^----^ 100003 key 175:175 ^ num 175:176 ^ 1 pair 175:176 ^ 1 grp 168:176 ^------^ 100003,1 pair 168:176 ^------^ 100003,1 lnav-0.7.0/test/datafile_simple.9000664 000765 000024 00000000762 12307146044 017131 0ustar00stackstaff000000 000000 12:01 12:01:22 12:01:22.123 key 0:0 time 0:5 ^---^ 12:01 pair 0:5 ^---^ 12:01 key 7:7 ^ time 7:15 ^------^ 12:01:22 pair 7:15 ^------^ 12:01:22 key 17:17 ^ time 17:29 ^----------^ 12:01:22.123 pair 17:29 ^----------^ 12:01:22.123 lnav-0.7.0/test/drive_data_scanner.cc000664 000765 000024 00000013736 12313321522 020035 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include "pcrepp.hh" #include "textview_curses.hh" #include "data_scanner.hh" #include "data_parser.hh" #include "log_format.hh" #include "log_format_loader.hh" using namespace std; const char *TMP_NAME = "scanned.tmp"; int main(int argc, char *argv[]) { int c, retval = EXIT_SUCCESS; bool prompt = false; { std::vector paths, errors; load_formats(paths, errors); } while ((c = getopt(argc, argv, "p")) != -1) { switch (c) { case 'p': prompt = true; break; default: retval = EXIT_FAILURE; break; } } argc -= optind; argv += optind; if (retval != EXIT_SUCCESS) {} else if (argc < 1) { fprintf(stderr, "error: expecting file name argument(s)\n"); retval = EXIT_FAILURE; } else { for (int lpc = 0; lpc < argc; lpc++) { istream *in; FILE * out; if (strcmp(argv[lpc], "-") == 0) { in = &cin; } else { ifstream *ifs = new ifstream(argv[lpc]); if (!ifs->is_open()) { fprintf(stderr, "error: unable to open file\n"); retval = EXIT_FAILURE; } else { in = ifs; } } if ((out = fopen(TMP_NAME, "w")) == NULL) { fprintf(stderr, "error: unable to temporary file for writing\n"); retval = EXIT_FAILURE; } else { auto_ptr format; char *log_line; bool found = false; char cmd[2048]; string line; int rc; getline(*in, line); if (strcmp(argv[lpc], "-") == 0) { line = " " + line; } log_line = (char *)alloca(line.length()); strcpy(log_line, &line[13]); vector &root_formats = log_format::get_root_formats(); vector::iterator iter; vector index; for (iter = root_formats.begin(); iter != root_formats.end() && !found; ++iter) { (*iter)->clear(); if ((*iter)->scan(index, 13, log_line, strlen(log_line))) { format = (*iter)->specialized(); found = true; } } string sub_line = line.substr(13); struct line_range body(0, sub_line.length()); shared_buffer share_manager; shared_buffer_ref sbr; sbr.share(share_manager, (char *)sub_line.c_str(), sub_line.size()); if (format.get() != NULL) { vector ll_values; string_attrs_t sa; format->annotate(sbr, sa, ll_values); body = find_string_attr_range(sa, &textview_curses::SA_BODY); } data_parser::TRACE_FILE = fopen("scanned.dpt", "w"); data_scanner ds(sub_line, body.lr_start, sub_line.length()); data_parser dp(&ds); dp.parse(); dp.print(out, dp.dp_pairs); fclose(out); sprintf(cmd, "diff -u %s %s", argv[lpc], TMP_NAME); rc = system(cmd); if (rc != 0) { if (prompt) { char resp[4]; printf("Would you like to update the original file? (y/N) "); fflush(stdout); scanf("%3s", resp); if (strcasecmp(resp, "y") == 0) { rename(TMP_NAME, argv[lpc]); } else{ retval = EXIT_FAILURE; } } else { fprintf(stderr, "error: mismatch\n"); retval = EXIT_FAILURE; } } fclose(data_parser::TRACE_FILE); data_parser::TRACE_FILE = NULL; } } } return retval; } lnav-0.7.0/test/drive_grep_proc.cc000664 000765 000024 00000007466 12311035743 017403 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include "grep_proc.hh" #include "line_buffer.hh" using namespace std; class my_source : public grep_proc_source { public: my_source(auto_fd &fd) : ms_offset(0) { this->ms_buffer.set_fd(fd); }; bool grep_value_for_line(int line_number, string &value_out) { bool retval = false; try { line_value lv; if (this->ms_buffer.read_line(this->ms_offset, lv)) { value_out = string(lv.lv_start, lv.lv_len); retval = true; } } catch (line_buffer::error &e) { fprintf(stderr, "error: source buffer error %d %s\n", this->ms_buffer.get_fd(), strerror(e.e_err)); } return retval; }; private: line_buffer ms_buffer; off_t ms_offset; }; class my_sink : public grep_proc_sink { public: my_sink() : ms_finished(false) { }; void grep_match(grep_proc &gp, grep_line_t line, int start, int end) { printf("%d:%d:%d\n", (int)line, start, end); }; void grep_capture(grep_proc &gp, grep_line_t line, int start, int end, char *capture) { fprintf(stderr, "%d(%d:%d)%s\n", (int)line, start, end, capture); }; void grep_end(grep_proc &gp) { this->ms_finished = true; }; bool ms_finished; }; int main(int argc, char *argv[]) { int retval = EXIT_SUCCESS; const char *errptr; auto_fd fd; pcre *code; int eoff; if (argc < 3) { fprintf(stderr, "error: expecting pattern and file arguments\n"); retval = EXIT_FAILURE; } else if ((fd = open(argv[2], O_RDONLY)) == -1) { perror("open"); retval = EXIT_FAILURE; } else if ((code = pcre_compile(argv[1], PCRE_CASELESS, &errptr, &eoff, NULL)) == NULL) { fprintf(stderr, "error: invalid pattern -- %s\n", errptr); } else { my_source ms(fd); fd_set read_fds; my_sink msink; int maxfd; FD_ZERO(&read_fds); grep_proc gp(code, ms, maxfd, read_fds); gp.queue_request(); gp.start(); gp.set_sink(&msink); while (!msink.ms_finished) { fd_set rfds = read_fds; select(maxfd + 1, &rfds, NULL, NULL, NULL); gp.check_fd_set(rfds); } } return retval; } lnav-0.7.0/test/drive_line_buffer.cc000664 000765 000024 00000011221 12311035743 017663 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "lnav_util.hh" #include "auto_fd.hh" #include "line_buffer.hh" using namespace std; int main(int argc, char *argv[]) { int c, rnd_iters = 5, retval = EXIT_SUCCESS; vector > index; auto_fd fd = STDIN_FILENO; off_t offset = 0; struct stat st; while ((c = getopt(argc, argv, "o:i:n:")) != -1) { switch (c) { case 'o': if (sscanf(optarg, FORMAT_OFF_T, &offset) != 1) { fprintf(stderr, "error: offset is not an integer -- %s\n", optarg); retval = EXIT_FAILURE; } break; case 'n': if (sscanf(optarg, "%d", &rnd_iters) != 1) { fprintf(stderr, "error: offset is not an integer -- %s\n", optarg); retval = EXIT_FAILURE; } break; case 'i': { FILE *file; if ((file = fopen(optarg, "r")) == NULL) { perror("open"); retval = EXIT_FAILURE; } else { int line_number = 1, line_offset; while (fscanf(file, "%d", &line_offset) == 1) { index.push_back( make_pair(line_number, line_offset)); line_number += 1; } fclose(file); file = NULL; } } break; default: retval = EXIT_FAILURE; break; } } argc -= optind; argv += optind; if (retval != EXIT_SUCCESS) { } else if ((argc == 0) && (index.size() > 0)) { fprintf(stderr, "error: cannot randomize stdin\n"); retval = EXIT_FAILURE; } else if ((argc > 0) && (fd = open(argv[0], O_RDONLY)) == -1) { perror("open"); retval = EXIT_FAILURE; } else if ((argc > 0) && (fstat(fd, &st) == -1)) { perror("fstat"); retval = EXIT_FAILURE; } else { try { off_t last_offset = offset; line_buffer lb; line_value lv; char *maddr; lb.set_fd(fd); if (index.size() == 0) { while (lb.read_line(offset, lv)) { lv.terminate(); printf("%s", lv.lv_start); if ((last_offset + lv.lv_len) < offset) printf("\n"); last_offset = offset; } } else if ((maddr = (char *)mmap(NULL, st.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, lb.get_fd(), 0)) == MAP_FAILED) { perror("mmap"); retval = EXIT_FAILURE; } else { off_t seq_offset = 0; while (lb.read_line(seq_offset, lv)) { } do { bool ret; int lpc; random_shuffle(index.begin(), index.end()); for (lpc = 0; lpc < index.size(); lpc++) { offset = index[lpc].second; ret = lb.read_line(offset, lv); assert(ret); assert(offset >= 0); assert(offset <= st.st_size); assert(memcmp(lv.lv_start, &maddr[index[lpc].second], lv.lv_len) == 0); } rnd_iters -= 1; } while (rnd_iters); printf("All done\n"); } } catch (line_buffer::error &e) { fprintf(stderr, "error: %s\n", strerror(e.e_err)); retval = EXIT_FAILURE; } } return retval; } lnav-0.7.0/test/drive_listview.cc000664 000765 000024 00000006770 12306075207 017271 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include "listview_curses.hh" using namespace std; static listview_curses lv; class my_source : public list_data_source { public: my_source() : ms_rows(2) { }; size_t listview_rows(const listview_curses &lv) { return this->ms_rows; }; void listview_value_for_row(const listview_curses &lv, vis_line_t row, attr_line_t &value_out) { if (row == 0) { value_out = "Hello"; } else if (row == 1) { value_out = "World!"; } else if (row < this->ms_rows) { char buffer[32]; snprintf(buffer, sizeof(buffer), "%d", (int)row); value_out = string(buffer); } else { assert(0); } }; size_t listview_size_for_row(const listview_curses &lv, vis_line_t row) { return 100; }; bool attrline_next_token(const view_curses &vc, int line, struct line_range &lr, int &attrs_out) { return false; }; int ms_rows; }; int main(int argc, char *argv[]) { int c, retval = EXIT_SUCCESS; bool wait_for_input = false; my_source ms; WINDOW *win; win = initscr(); lv.set_data_source(&ms); lv.set_window(win); noecho(); while ((c = getopt(argc, argv, "y:t:l:r:h:w")) != -1) { switch (c) { case 'y': lv.set_y(atoi(optarg)); break; case 'h': lv.set_height(vis_line_t(atoi(optarg))); break; case 't': lv.set_top(vis_line_t(atoi(optarg))); break; case 'l': lv.set_left(atoi(optarg)); break; case 'w': wait_for_input = true; break; case 'r': ms.ms_rows = atoi(optarg); break; } } lv.do_update(); refresh(); if (wait_for_input) getch(); endwin(); return retval; } lnav-0.7.0/test/drive_logfile.cc000664 000765 000024 00000007641 12311035743 017037 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include "logfile.hh" #include "log_format.hh" #include "log_format_loader.hh" using namespace std; typedef enum { MODE_NONE, MODE_ECHO, MODE_LINE_COUNT, MODE_TIMES, MODE_LEVELS, } dl_mode_t; time_t time(time_t *_unused) { return 1194107018; } int main(int argc, char *argv[]) { int c, retval = EXIT_SUCCESS; dl_mode_t mode = MODE_NONE; string expected_format; { std::vector paths, errors; load_formats(paths, errors); } while ((c = getopt(argc, argv, "ef:ltv")) != -1) { switch (c) { case 'f': expected_format = optarg; break; case 'e': mode = MODE_ECHO; break; case 'l': mode = MODE_LINE_COUNT; break; case 't': mode = MODE_TIMES; break; case 'v': mode = MODE_LEVELS; break; } } argc -= optind; argv += optind; if (retval == EXIT_FAILURE) { } else if (argc == 0) { fprintf(stderr, "error: expecting log file name\n"); } else { logfile lf(argv[0]); struct stat st; stat(argv[0], &st); assert(strcmp(argv[0], lf.get_filename().c_str()) == 0); lf.rebuild_index(); if (expected_format == "") { assert(lf.get_format() == NULL); } else { //printf("%s %s\n", lf.get_format()->get_name().c_str(), expected_format.c_str()); assert(lf.get_format()->get_name() == expected_format); } if (!lf.is_compressed()) { assert(lf.get_modified_time() == st.st_mtime); } switch (mode) { case MODE_NONE: break; case MODE_ECHO: for (logfile::iterator iter = lf.begin(); iter != lf.end(); ++iter) { printf("%s\n", lf.read_line(iter).c_str()); } break; case MODE_LINE_COUNT: printf("%zd\n", lf.size()); break; case MODE_TIMES: for (logfile::iterator iter = lf.begin(); iter != lf.end(); ++iter) { char buffer[1024]; time_t lt; lt = iter->get_time(); strftime(buffer, sizeof(buffer), "%b %d %H:%M:%S %Y", gmtime(<)); printf("%s -- %03d\n", buffer, iter->get_millis()); } break; case MODE_LEVELS: for (logfile::iterator iter = lf.begin(); iter != lf.end(); ++iter) { printf("0x%02x\n", iter->get_level()); } break; } } return retval; } lnav-0.7.0/test/drive_mvwattrline.cc000644 000765 000024 00000006566 12306615201 017772 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include "view_curses.hh" int main(int argc, char *argv[]) { int c, retval = EXIT_SUCCESS; bool wait_for_input = false; while ((c = getopt(argc, argv, "w")) != -1) { switch (c) { case 'w': wait_for_input = true; break; } } { screen_curses sc; WINDOW *win = sc.get_window(); struct line_range lr(0, 40); attr_line_t al; int y = 0; noecho(); view_colors::singleton().init(); al.with_string("Plain text"); view_curses::mvwattrline(win, y++, 0, al, lr); al.clear().with_string("\tLeading tab") .with_attr(string_attr(line_range(0, 1), &view_curses::VC_STYLE, A_REVERSE)); view_curses::mvwattrline(win, y++, 0, al, lr); al.clear().with_string("Tab\twith text") .with_attr(string_attr(line_range(1, 4), &view_curses::VC_STYLE, A_REVERSE)); view_curses::mvwattrline(win, y++, 0, al, lr); al.clear().with_string("Tab\twith text #2") .with_attr(string_attr(line_range(3, 4), &view_curses::VC_STYLE, A_REVERSE)); view_curses::mvwattrline(win, y++, 0, al, lr); al.clear().with_string("Text with mixed attributes.") .with_attr(string_attr(line_range(5, 9), &view_curses::VC_STYLE, view_colors::ansi_color_pair(COLOR_RED, COLOR_BLACK))) .with_attr(string_attr(line_range(7, 12), &view_curses::VC_STYLE, A_REVERSE)); view_curses::mvwattrline(win, y++, 0, al, lr); wmove(win, y, 0); refresh(); if (wait_for_input) { getch(); } } return retval; } lnav-0.7.0/test/drive_readline_curses.cc000664 000765 000024 00000007532 12301137170 020560 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #ifdef HAVE_SYS_TTYDEFAULTS_H #include #endif #include #include "readline_curses.hh" using namespace std; static readline_context::command_map_t COMMANDS; static struct { bool dd_active; readline_curses *dd_rl_view; volatile sig_atomic_t dd_looping; } drive_data; static void rl_callback(void *dummy, readline_curses *rc) { string line = rc->get_value(); if (line == "quit") drive_data.dd_looping = false; fprintf(stderr, "callback\n"); drive_data.dd_active = false; } static void rl_timeout(void *dummy, readline_curses *rc) { fprintf(stderr, "timeout\n"); } int main(int argc, char *argv[]) { int c, fd, maxfd, retval = EXIT_SUCCESS; fd = open("/tmp/lnav.err", O_WRONLY|O_CREAT|O_APPEND, 0666); dup2(fd, STDERR_FILENO); close(fd); fprintf(stderr, "startup\n"); while ((c = getopt(argc, argv, "h")) != -1) { switch (c) { case 'h': break; default: break; } } readline_context context("test", &COMMANDS); readline_curses rlc; fd_set rfds; rlc.add_context(1, context); rlc.start(); drive_data.dd_rl_view = &rlc; FD_ZERO(&rfds); FD_SET(STDIN_FILENO, &rfds); screen_curses sc; keypad(stdscr, TRUE); nonl(); cbreak(); noecho(); nodelay(sc.get_window(), 1); rlc.set_window(sc.get_window()); rlc.set_y(-1); rlc.set_perform_action(readline_curses::action(rl_callback)); rlc.set_timeout_action(readline_curses::action(rl_timeout)); maxfd = max(STDIN_FILENO, rlc.update_fd_set(rfds)); drive_data.dd_looping = true; while (drive_data.dd_looping) { fd_set ready_rfds = rfds; int rc; rlc.do_update(); refresh(); rc = select(maxfd + 1, &ready_rfds, NULL, NULL, NULL); if (rc > 0) { if (FD_ISSET(STDIN_FILENO, &ready_rfds)) { int ch; while ((ch = getch()) != ERR) { switch (ch) { case CEOF: case KEY_RESIZE: break; default: if (drive_data.dd_active) { rlc.handle_key(ch); } else if (ch == ':') { rlc.focus(1, ":"); drive_data.dd_active = true; } break; } } } rlc.check_fd_set(ready_rfds); } } return retval; } lnav-0.7.0/test/drive_sequencer.cc000664 000765 000024 00000007712 12311035743 017407 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "pcrepp.hh" #include "logfile.hh" #include "sequence_sink.hh" #include "sequence_matcher.hh" using namespace std; class my_source : public grep_proc_source { public: my_source(auto_fd &fd) : ms_offset(0) { this->ms_buffer.set_fd(fd); }; bool grep_value_for_line(int line_number, string &value_out) { bool retval = false; try { line_value lv; if (this->ms_buffer.read_line(this->ms_offset, lv)) { value_out = string(lv.lv_start, lv.lv_len); retval = true; } } catch (line_buffer::error &e) { fprintf(stderr, "error: source buffer error %d %s\n", this->ms_buffer.get_fd(), strerror(e.e_err)); } return retval; }; private: line_buffer ms_buffer; off_t ms_offset; }; int main(int argc, char *argv[]) { int c, retval = EXIT_SUCCESS; const char *errptr; auto_fd fd; pcre *code; int eoff; if (argc < 3) { fprintf(stderr, "error: expecting pattern and file arguments\n"); retval = EXIT_FAILURE; } else if ((fd = open(argv[2], O_RDONLY)) == -1) { perror("open"); retval = EXIT_FAILURE; } else if ((code = pcre_compile(argv[1], PCRE_CASELESS, &errptr, &eoff, NULL)) == NULL) { fprintf(stderr, "error: invalid pattern -- %s\n", errptr); } else { my_source ms(fd); fd_set read_fds; int maxfd; sequence_matcher::field_col_t fc; fc.resize(2); sequence_matcher::field_row_t &frf = fc.front(); frf.resize(2); frf[0] = "eth0"; frf[1] = "eth0"; sequence_matcher::field_row_t &frb = fc.back(); frb.resize(2); frb[0] = "up"; frb[1] = "down"; static bookmark_type_t SEQUENCE; sequence_matcher sm(fc); vis_bookmarks bm; sequence_sink ss(sm, bm[&SEQUENCE]); FD_ZERO(&read_fds); grep_proc gp(code, ms, maxfd, read_fds); gp.queue_request(); gp.start(); gp.set_sink(&ss); while (bm[&SEQUENCE].size() == 0) { fd_set rfds = read_fds; select(maxfd + 1, &rfds, NULL, NULL, NULL); gp.check_fd_set(rfds); } for (bookmark_vector::iterator iter = bm[&SEQUENCE].begin(); iter != bm[&SEQUENCE].end(); ++iter) { printf("%d\n", (const int)*iter); } } return retval; } lnav-0.7.0/test/drive_sql.cc000664 000765 000024 00000003264 12211635054 016212 0ustar00stackstaff000000 000000 #include #include #include #include #include #include "lnav.hh" #include "auto_mem.hh" #include "sqlite-extension-func.h" struct callback_state { int cs_row; }; struct _lnav_data lnav_data; static int sql_callback(void *ptr, int ncols, char **colvalues, char **colnames) { struct callback_state *cs = (struct callback_state *)ptr; printf("Row %d:\n", cs->cs_row); for (int lpc = 0; lpc < ncols; lpc++) { printf(" Column %10s: %s\n", colnames[lpc], colvalues[lpc]); } cs->cs_row += 1; return 0; } int main(int argc, char *argv[]) { int retval = EXIT_SUCCESS; auto_mem db(sqlite3_close); if (argc != 2) { fprintf(stderr, "error: expecting an SQL statement\n"); retval = EXIT_FAILURE; } else if (sqlite3_open(":memory:", db.out()) != SQLITE_OK) { fprintf(stderr, "error: unable to make sqlite memory database\n"); retval = EXIT_FAILURE; } else { auto_mem errmsg(sqlite3_free); struct callback_state state; memset(&state, 0, sizeof(state)); { int register_collation_functions(sqlite3 * db); register_sqlite_funcs(db.in(), sqlite_registration_funcs); register_collation_functions(db.in()); } if (sqlite3_exec(db.in(), argv[1], sql_callback, &state, errmsg.out()) != SQLITE_OK) { fprintf(stderr, "error: sqlite3_exec failed -- %s\n", errmsg.in()); retval = EXIT_FAILURE; } } return retval; } lnav-0.7.0/test/drive_view_colors.cc000664 000765 000024 00000005312 12211635054 017742 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include "view_curses.hh" class test_colors : public view_curses { public: test_colors() : tc_window(NULL) { } void do_update(void) { int lpc; for (lpc = 0; lpc < 16; lpc++) { view_colors::role_t role; char label[64]; attr_line_t al; line_range lr; role = view_colors::singleton().next_highlight(); snprintf(label, sizeof(label), "This is line: %d", lpc); al = label; lr.lr_start = 0; lr.lr_end = 40; this->mvwattrline(this->tc_window, lpc, 0, al, lr, role); } }; WINDOW *tc_window; }; int main(int argc, char *argv[]) { int c, retval = EXIT_SUCCESS; bool wait_for_input = false; WINDOW *win; test_colors tc; win = initscr(); noecho(); while ((c = getopt(argc, argv, "w")) != -1) { switch (c) { case 'w': wait_for_input = true; break; } } view_colors::singleton().init(); tc.tc_window = win; tc.do_update(); refresh(); if (wait_for_input) { getch(); } endwin(); return retval; } lnav-0.7.0/test/drive_vt52_curses.cc000664 000765 000024 00000006451 12211635054 017600 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include "view_curses.hh" #include "vt52_curses.hh" #if defined HAVE_NCURSESW_CURSES_H # include # include #elif defined HAVE_NCURSESW_H # include # include #elif defined HAVE_NCURSES_CURSES_H # include # include #elif defined HAVE_NCURSES_H # include # include #elif defined HAVE_CURSES_H # include # include #else # error "SysV or X/Open-compatible Curses header file required" #endif #undef set_window int main(int argc, char *argv[]) { int lpc, c, fd, retval = EXIT_SUCCESS; vt52_curses vt; fd = open("/tmp/lnav.err", O_WRONLY|O_CREAT|O_APPEND, 0666); dup2(fd, STDERR_FILENO); close(fd); fprintf(stderr, "startup\n"); while ((c = getopt(argc, argv, "y:")) != -1) { switch (c) { case 'y': vt.set_y(atoi(optarg)); break; } } for (lpc = 0; lpc < 1000; lpc++) { int len; assert(vt.map_input(random(), len) != NULL); assert(len > 0); } tgetent(NULL, "vt52"); { static const char *CANNED_INPUT[] = { "abc", "\r", tgetstr("ce", NULL), "de", "\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n", "abc", "\x2", "\a", "ab\bcdef", 0 }; screen_curses sc; noecho(); vt.set_window(sc.get_window()); for (lpc = 0; CANNED_INPUT[lpc]; lpc++) { vt.map_output(CANNED_INPUT[lpc], strlen(CANNED_INPUT[lpc])); vt.do_update(); refresh(); getch(); } getch(); } return retval; } lnav-0.7.0/test/formats/000775 000765 000024 00000000000 12315725122 015362 5ustar00stackstaff000000 000000 lnav-0.7.0/test/listview_output.0000664 000765 000024 00000001532 12315442240 017254 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a48656c6c6f1b5b3734430e780f1b5b6d1b5b323b31480e0f1b5b6d576f726c64211b5b3733430e780f1b5b6d1b5b333b3830480e780f1b5b6d1b5b343b3830480e780f1b5b6d1b5b353b3830480e780f1b5b6d1b5b363b3830480e780f1b5b6d1b5b373b3830480e780f1b5b6d1b5b383b3830480e780f1b5b6d1b5b393b3830480e780f1b5b6d1b5b31303b3830480e780f1b5b6d1b5b31313b3830480e780f1b5b6d1b5b31323b3830480e780f1b5b6d1b5b31333b3830480e780f1b5b6d1b5b31343b3830480e780f1b5b6d1b5b31353b3830480e780f1b5b6d1b5b31363b3830480e780f1b5b6d1b5b31373b3830480e780f1b5b6d1b5b31383b3830480e780f1b5b6d1b5b31393b3830480e780f1b5b6d1b5b32303b3830480e780f1b5b6d1b5b32313b3830480e780f1b5b6d1b5b32323b3830480e780f1b5b6d1b5b32333b3830480e780f1b5b6d1b5b32343b3830480e0f1b5b6d080e780f1b5b6d080e1b5b34680f1b5b6d201b5b346c0d1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e lnav-0.7.0/test/listview_output.1000664 000765 000024 00000001476 12315442307 017270 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a576f726c64211b5b3733430e780f1b5b6d1b5b323b3830480e780f1b5b6d1b5b333b3830480e780f1b5b6d1b5b343b3830480e780f1b5b6d1b5b353b3830480e780f1b5b6d1b5b363b3830480e780f1b5b6d1b5b373b3830480e780f1b5b6d1b5b383b3830480e780f1b5b6d1b5b393b3830480e780f1b5b6d1b5b31303b3830480e780f1b5b6d1b5b31313b3830480e780f1b5b6d1b5b31323b3830480e780f1b5b6d1b5b31333b3830480e780f1b5b6d1b5b31343b3830480e780f1b5b6d1b5b31353b3830480e780f1b5b6d1b5b31363b3830480e780f1b5b6d1b5b31373b3830480e780f1b5b6d1b5b31383b3830480e780f1b5b6d1b5b31393b3830480e780f1b5b6d1b5b32303b3830480e780f1b5b6d1b5b32313b3830480e780f1b5b6d1b5b32323b3830480e780f1b5b6d1b5b32333b3830480e780f1b5b6d1b5b32343b3830480e0f1b5b6d080e780f1b5b6d080e1b5b34680f1b5b6d201b5b346c0d1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e lnav-0.7.0/test/listview_output.2000664 000765 000024 00000001526 12315442320 017260 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a656c6c6f1b5b3735430e780f1b5b6d1b5b323b31480e0f1b5b6d6f726c64211b5b3734430e780f1b5b6d1b5b333b3830480e780f1b5b6d1b5b343b3830480e780f1b5b6d1b5b353b3830480e780f1b5b6d1b5b363b3830480e780f1b5b6d1b5b373b3830480e780f1b5b6d1b5b383b3830480e780f1b5b6d1b5b393b3830480e780f1b5b6d1b5b31303b3830480e780f1b5b6d1b5b31313b3830480e780f1b5b6d1b5b31323b3830480e780f1b5b6d1b5b31333b3830480e780f1b5b6d1b5b31343b3830480e780f1b5b6d1b5b31353b3830480e780f1b5b6d1b5b31363b3830480e780f1b5b6d1b5b31373b3830480e780f1b5b6d1b5b31383b3830480e780f1b5b6d1b5b31393b3830480e780f1b5b6d1b5b32303b3830480e780f1b5b6d1b5b32313b3830480e780f1b5b6d1b5b32323b3830480e780f1b5b6d1b5b32333b3830480e780f1b5b6d1b5b32343b3830480e0f1b5b6d080e780f1b5b6d080e1b5b34680f1b5b6d201b5b346c0d1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e lnav-0.7.0/test/listview_output.3000664 000765 000024 00000001474 12315442367 017276 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a6f726c64211b5b3734430e780f1b5b6d1b5b323b3830480e780f1b5b6d1b5b333b3830480e780f1b5b6d1b5b343b3830480e780f1b5b6d1b5b353b3830480e780f1b5b6d1b5b363b3830480e780f1b5b6d1b5b373b3830480e780f1b5b6d1b5b383b3830480e780f1b5b6d1b5b393b3830480e780f1b5b6d1b5b31303b3830480e780f1b5b6d1b5b31313b3830480e780f1b5b6d1b5b31323b3830480e780f1b5b6d1b5b31333b3830480e780f1b5b6d1b5b31343b3830480e780f1b5b6d1b5b31353b3830480e780f1b5b6d1b5b31363b3830480e780f1b5b6d1b5b31373b3830480e780f1b5b6d1b5b31383b3830480e780f1b5b6d1b5b31393b3830480e780f1b5b6d1b5b32303b3830480e780f1b5b6d1b5b32313b3830480e780f1b5b6d1b5b32323b3830480e780f1b5b6d1b5b32333b3830480e780f1b5b6d1b5b32343b3830480e0f1b5b6d080e780f1b5b6d080e1b5b34680f1b5b6d201b5b346c0d1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e lnav-0.7.0/test/listview_output.4000664 000765 000024 00000002366 12315442404 017270 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a0a48656c6c6f1b5b3734430e780f1b5b6d1b5b333b31480e0f1b5b6d576f726c64211b5b3733430e780f1b5b6d1b5b343b31480e0f1b5b6d321b5b3738430e780f1b5b6d1b5b353b31480e0f1b5b6d331b5b3738430e780f1b5b6d1b5b363b31480e0f1b5b6d341b5b3738430e780f1b5b6d1b5b373b31480e0f1b5b6d351b5b3738430e780f1b5b6d1b5b383b31480e0f1b5b6d361b5b3738430e780f1b5b6d1b5b393b31480e0f1b5b6d371b5b3738430e780f1b5b6d1b5b31303b31480e0f1b5b6d381b5b3738430e780f1b5b6d1b5b31313b31480e0f1b5b6d391b5b3738430e780f1b5b6d1b5b31323b31480e0f1b5b6d31301b5b3737430e780f1b5b6d1b5b31333b31480e0f1b5b6d31311b5b3737430e780f1b5b6d1b5b31343b31480e0f1b5b6d31321b5b3737430e780f1b5b6d1b5b31353b31480e0f1b5b6d31331b5b3737430e780f1b5b6d1b5b31363b31480e0f1b5b6d31341b5b3737430e780f1b5b6d1b5b31373b31480e0f1b5b6d31351b5b3737430e780f1b5b6d1b5b31383b31480e0f1b5b6d31361b5b3737430e780f1b5b6d1b5b31393b31480e0f1b5b6d31371b5b3737430e780f1b5b6d1b5b32303b31480e0f1b5b6d31381b5b3737430e780f1b5b6d1b5b32313b31480e0f1b5b6d31391b5b3737430e780f1b5b6d1b5b32323b31480e0f1b5b6d32301b5b3737430e780f1b5b6d1b5b32333b31480e0f1b5b6d32311b5b3737430e780f1b5b6d1b5b32343b31480e0f1b5b6d32321b5b373743080e780f1b5b6d080e1b5b34680f1b5b6d201b5b346c0d1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e lnav-0.7.0/test/listview_output.5000664 000765 000024 00000002272 12315442423 017266 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a0a48656c6c6f1b5b3734430e780f1b5b6d1b5b333b31480e0f1b5b6d576f726c64211b5b3733430e780f1b5b6d1b5b343b31480e0f1b5b6d321b5b3738430e780f1b5b6d1b5b353b31480e0f1b5b6d331b5b3738430e780f1b5b6d1b5b363b31480e0f1b5b6d341b5b3738430e780f1b5b6d1b5b373b31480e0f1b5b6d351b5b3738430e780f1b5b6d1b5b383b31480e0f1b5b6d361b5b3738430e780f1b5b6d1b5b393b31480e0f1b5b6d371b5b3738430e780f1b5b6d1b5b31303b31480e0f1b5b6d381b5b3738430e780f1b5b6d1b5b31313b31480e0f1b5b6d391b5b3738430e780f1b5b6d1b5b31323b31480e0f1b5b6d31301b5b3737430e780f1b5b6d1b5b31333b31480e0f1b5b6d31311b5b3737430e780f1b5b6d1b5b31343b31480e0f1b5b6d31321b5b3737430e780f1b5b6d1b5b31353b31480e0f1b5b6d31331b5b3737430e780f1b5b6d1b5b31363b31480e0f1b5b6d31341b5b3737430e780f1b5b6d1b5b31373b31480e0f1b5b6d31351b5b3737430e780f1b5b6d1b5b31383b31480e0f1b5b6d31361b5b3737430e780f1b5b6d1b5b31393b31480e0f1b5b6d31371b5b3737430e780f1b5b6d1b5b32303b31480e0f1b5b6d31381b5b3737430e780f1b5b6d1b5b32313b31480e0f1b5b6d31391b5b3737430e780f1b5b6d1b5b32323b31480e0f1b5b6d32301b5b3737430e780f1b5b6d1b5b32333b31480e0f1b5b6d32311b5b3737430e780f1b5b6d1b5b32333b31480e0f1b5b6d1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e lnav-0.7.0/test/listview_output.6000664 000765 000024 00000002264 12315442441 017270 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a0a576f726c64211b5b3733430e780f1b5b6d1b5b333b31480e0f1b5b6d321b5b3738430e780f1b5b6d1b5b343b31480e0f1b5b6d331b5b3738430e780f1b5b6d1b5b353b31480e0f1b5b6d341b5b3738430e780f1b5b6d1b5b363b31480e0f1b5b6d351b5b3738430e780f1b5b6d1b5b373b31480e0f1b5b6d361b5b3738430e780f1b5b6d1b5b383b31480e0f1b5b6d371b5b3738430e780f1b5b6d1b5b393b31480e0f1b5b6d381b5b3738430e780f1b5b6d1b5b31303b31480e0f1b5b6d391b5b3738430e780f1b5b6d1b5b31313b31480e0f1b5b6d31301b5b3737430e780f1b5b6d1b5b31323b31480e0f1b5b6d31311b5b3737430e780f1b5b6d1b5b31333b31480e0f1b5b6d31321b5b3737430e780f1b5b6d1b5b31343b31480e0f1b5b6d31331b5b3737430e780f1b5b6d1b5b31353b31480e0f1b5b6d31341b5b3737430e780f1b5b6d1b5b31363b31480e0f1b5b6d31351b5b3737430e780f1b5b6d1b5b31373b31480e0f1b5b6d31361b5b3737430e780f1b5b6d1b5b31383b31480e0f1b5b6d31371b5b3737430e780f1b5b6d1b5b31393b31480e0f1b5b6d31381b5b3737430e780f1b5b6d1b5b32303b31480e0f1b5b6d31391b5b3737430e780f1b5b6d1b5b32313b31480e0f1b5b6d32301b5b3737430e780f1b5b6d1b5b32323b31480e0f1b5b6d32311b5b3737430e780f1b5b6d1b5b32333b31480e0f1b5b6d32321b5b3737430e780f1b5b6d1b5b32333b31480e0f1b5b6d1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e lnav-0.7.0/test/log-samples/000775 000765 000024 00000000000 12315725123 016133 5ustar00stackstaff000000 000000 lnav-0.7.0/test/logfile_access_log.0000664 000765 000024 00000000537 12211635055 017600 0ustar00stackstaff000000 000000 192.168.202.254 - - [20/Jul/2009:22:59:26 +0000] "GET /vmw/cgi/tramp HTTP/1.0" 200 134 "-" "gPXE/0.9.7" 192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkboot.gz HTTP/1.0" 404 46210 "-" "gPXE/0.9.7" 192.168.202.254 - - [20/Jul/2009:22:59:29 +0000] "GET /vmw/vSphere/default/vmkernel.gz HTTP/1.0" 200 78929 "-" "gPXE/0.9.7" lnav-0.7.0/test/logfile_access_log.1000664 000765 000024 00000000100 12211635055 017563 0ustar00stackstaff000000 000000 10.112.81.15 - - [15/Feb/2013:06:00:31 +0000] "-" 400 0 "-" "-" lnav-0.7.0/test/logfile_empty.0000664 000765 000024 00000000000 12211635055 016615 0ustar00stackstaff000000 000000 lnav-0.7.0/test/logfile_generic.0000664 000765 000024 00000000051 12211635055 017101 0ustar00stackstaff000000 000000 2012-07-02 10:22:40,672:DEBUG:foo bar bazlnav-0.7.0/test/logfile_glog.0000664 000765 000024 00000001040 10713036764 016423 0ustar00stackstaff000000 000000 E0517 15:04:22.619632 1952452992 logging_unittest.cc:253] Log every 3, iteration 19 I0517 15:04:22.619642 1952452992 logging_unittest.cc:259] Log if every 1, iteration 19 I0517 15:04:22.619740 1952452992 logging_unittest.cc:259] Log if every 1, iteration 20 W0517 15:04:22.619751 1952452992 logging_unittest.cc:263] log_if this I0517 15:04:22.619760 1952452992 logging_unittest.cc:267] array I0517 15:04:22.619768 1952452992 logging_unittest.cc:269] const array E0517 15:04:22.619776 1952452992 logging_unittest.cc:271] foo 1000 0000001000 3e8 lnav-0.7.0/test/logfile_json.json000644 000765 000024 00000000305 12305015727 017252 0ustar00stackstaff000000 000000 {"ts": "2013-09-06T20:00:49.124817Z", "lvl": "INFO", "msg": "Starting up service"} {"ts": "2013-09-06T22:00:49.124817Z", "lvl": "INFO", "msg": "Shutting down service", "user": "steve@example.com"} lnav-0.7.0/test/logfile_multiline.0000664 000765 000024 00000000157 12304746074 017505 0ustar00stackstaff000000 000000 2009-07-20 22:59:27,672:DEBUG:Hello, World! How are you today? 2009-07-20 22:59:30,221:ERROR:Goodbye, World! lnav-0.7.0/test/logfile_strace_log.0000664 000765 000024 00000001463 10713036764 017626 0ustar00stackstaff000000 000000 08:09:33.814936 execve("/bin/ls", ["ls"], [/* 38 vars */]) = 0 <0.000264> 08:09:33.815688 brk(0) = 0x1513000 <0.000016> 08:09:33.815801 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9100b05000 <0.000019> 08:09:33.815943 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) <0.000019> 08:09:33.816083 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9100b03000 <0.000018> 08:09:33.816206 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) <0.000019> 08:09:33.816326 open("/etc/ld.so.cache", O_RDONLY) = 3 <0.000023> 08:09:33.816428 fstat(3, {st_mode=S_IFREG|0644, st_size=102143, ...}) = 0 <0.000015> 08:09:33.816577 mmap(NULL, 102143, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9100aea000 <0.000019> lnav-0.7.0/test/logfile_syslog.0000664 000765 000024 00000000600 12235503164 017006 0ustar00stackstaff000000 000000 Nov 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed Nov 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt Nov 3 09:23:38 veridian automount[7999]: lookup(file): lookup for opt failed Nov 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages lnav-0.7.0/test/logfile_syslog.1000664 000765 000024 00000000600 10713120144 016777 0ustar00stackstaff000000 000000 Dec 3 09:23:38 veridian automount[7998]: lookup(file): lookup for foobar failed Dec 3 09:23:38 veridian automount[16442]: attempting to mount entry /auto/opt Dec 3 09:23:38 veridian automount[7999]: lookup(file): lookup for opt failed Jan 3 09:47:02 veridian sudo: timstack : TTY=pts/6 ; PWD=/auto/wstimstack/rpms/lbuild/test ; USER=root ; COMMAND=/usr/bin/tail /var/log/messages lnav-0.7.0/test/logfile_tcsh_history.0000664 000765 000024 00000000063 12211635055 020212 0ustar00stackstaff000000 000000 #+1162490366 ./drive_vt52_curses #+1162490385 exit lnav-0.7.0/test/logfile_with_a_really_long_name_to_test_a_bug_with_long_names.0000664 000765 000024 00000000016 12211635055 030463 0ustar00stackstaff000000 000000 Hello, World! lnav-0.7.0/test/Makefile.am000664 000765 000024 00000013422 12315442471 015750 0ustar00stackstaff000000 000000 TESTS_ENVIRONMENT = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT LOG_COMPILER = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT simple-db.db: simple-db.sql rm -f $@ $(SQLITE3_CMD) $@ < $(srcdir)/simple-db.sql AM_CPPFLAGS = \ -I$(top_srcdir)/src \ $(SQLITE3_CFLAGS) # AM_CFLAGS = -fprofile-arcs -ftest-coverage # AM_CXXFLAGS = -fprofile-arcs -ftest-coverage check_PROGRAMS = \ drive_data_scanner \ drive_line_buffer \ drive_grep_proc \ drive_listview \ drive_logfile \ drive_mvwattrline \ drive_sequencer \ drive_sql \ drive_view_colors \ drive_vt52_curses \ drive_readline_curses \ slicer \ scripty \ test_ansi_scrubber \ test_auto_fd \ test_auto_mem \ test_bookmarks \ test_date_time_scanner \ test_grep_proc2 \ test_hist_source \ test_line_buffer2 \ test_log_accel \ test_pcrepp \ test_top_status \ test_yajlpp AM_LDFLAGS = \ $(STATIC_LDFLAGS) \ $(SQLITE3_LDFLAGS) \ -pthread LDADD = -lz test_ansi_scrubber_SOURCES = test_ansi_scrubber.cc test_ansi_scrubber_LDADD = ../src/libdiag.a $(CURSES_LIB) test_auto_fd_SOURCES = test_auto_fd.cc test_auto_fd_LDADD = ../src/libdiag.a test_auto_mem_SOURCES = test_auto_mem.cc test_bookmarks_SOURCES = test_bookmarks.cc test_bookmarks_LDADD = ../src/libdiag.a test_date_time_scanner_SOURCES = test_date_time_scanner.cc test_date_time_scanner_LDADD = ../src/libdiag.a $(SQLITE3_LIBS) -lcrypto test_grep_proc2_SOURCES = test_grep_proc2.cc test_grep_proc2_LDADD = ../src/libdiag.a $(PCRE_LIBS) -lz test_hist_source_SOURCES = test_hist_source.cc test_hist_source_LDADD = ../src/libdiag.a $(CURSES_LIB) -lz test_line_buffer2_SOURCES = test_line_buffer2.cc test_line_buffer2_LDADD = ../src/libdiag.a test_log_accel_SOURCES = test_log_accel.cc test_log_accel_LDADD = ../src/libdiag.a test_pcrepp_SOURCES = test_pcrepp.cc test_pcrepp_LDADD = ../src/libdiag.a $(PCRE_LIBS) -lz test_top_status_SOURCES = test_top_status.cc test_top_status_LDADD = ../src/libdiag.a $(CURSES_LIB) $(PCRE_LIBS) $(SQLITE3_LIBS) -lz test_yajlpp_SOURCES = test_yajlpp.cc test_yajlpp_LDADD = ../src/libdiag.a drive_line_buffer_SOURCES = drive_line_buffer.cc drive_line_buffer_LDADD = ../src/libdiag.a $(CURSES_LIB) -lz drive_grep_proc_SOURCES = drive_grep_proc.cc drive_grep_proc_LDADD = ../src/libdiag.a $(PCRE_LIBS) -lz drive_listview_SOURCES = drive_listview.cc drive_listview_LDADD = ../src/libdiag.a $(CURSES_LIB) -lz drive_logfile_SOURCES = drive_logfile.cc drive_logfile_LDADD = \ ../src/libdiag.a \ ../src/default-log-formats-json.o \ ../src/dump-pid-sh.o \ $(CURSES_LIB) \ $(SQLITE3_LIBS) \ $(PCRE_LIBS) \ -lpcrecpp drive_sequencer_SOURCES = drive_sequencer.cc drive_sequencer_LDADD = ../src/libdiag.a $(CURSES_LIB) $(SQLITE3_LIBS) drive_data_scanner_SOURCES = \ drive_data_scanner.cc drive_data_scanner_LDADD = \ ../src/libdiag.a \ ../src/default-log-formats-json.o \ ../src/dump-pid-sh.o \ $(PCRE_LIBS) \ $(SQLITE3_LIBS) \ -lpcrecpp \ $(CURSES_LIB) drive_mvwattrline_SOURCES = drive_mvwattrline.cc drive_mvwattrline_LDADD = ../src/libdiag.a $(CURSES_LIB) drive_view_colors_SOURCES = drive_view_colors.cc drive_view_colors_LDADD = ../src/libdiag.a $(CURSES_LIB) drive_vt52_curses_SOURCES = drive_vt52_curses.cc drive_vt52_curses_LDADD = ../src/libdiag.a $(CURSES_LIB) drive_readline_curses_SOURCES = drive_readline_curses.cc drive_readline_curses_LDADD = ../src/libdiag.a $(READLINE_LIBS) $(CURSES_LIB) drive_sql_SOURCES = \ drive_sql.cc drive_sql_LDADD = \ ../src/libdiag.a \ $(SQLITE3_LIBS) \ $(PCRE_LIBS) \ $(CURSES_LIB) \ $(READLINE_LIBS) \ -lpcrecpp slicer_SOURCES = slicer.cc slicer_LDADD = ../src/libdiag.a scripty_SOURCES = scripty.cc scripty_LDADD = ../src/libdiag.a dist_noinst_SCRIPTS = \ parser_debugger.py \ test_cmds.sh \ test_data_parser.sh \ test_grep_proc.sh \ test_json_format.sh \ test_line_buffer.sh \ test_listview.sh \ test_logfile.sh \ test_mvwattrline.sh \ test_sessions.sh \ test_sql.sh \ test_sql_coll_func.sh \ test_sql_str_func.sh \ test_sql_fs_func.sh \ test_view_colors.sh \ test_vt52_curses.sh dist_noinst_DATA = \ ansi-colors.0.in \ datafile_simple.0 \ datafile_simple.1 \ datafile_simple.2 \ datafile_simple.3 \ datafile_simple.4 \ datafile_simple.5 \ datafile_simple.6 \ datafile_simple.7 \ datafile_simple.8 \ datafile_simple.9 \ datafile_simple.10 \ datafile_simple.11 \ listview_output.0 \ listview_output.1 \ listview_output.2 \ listview_output.3 \ listview_output.4 \ listview_output.5 \ listview_output.6 \ logfile_access_log.0 \ logfile_access_log.1 \ logfile_empty.0 \ logfile_generic.0 \ logfile_glog.0 \ logfile_json.json \ logfile_multiline.0 \ logfile_strace_log.0 \ logfile_syslog.0 \ logfile_syslog.1 \ logfile_tcsh_history.0 \ logfile_with_a_really_long_name_to_test_a_bug_with_long_names.0 \ mvwattrline_output.0 \ simple-db.sql \ view_colors_output.0 \ vt52_curses_input.0 \ vt52_curses_input.1 \ vt52_curses_output.0 \ vt52_curses_output.1 \ formats/jsontest/format.json \ log-samples/sample-27353a72ba4025448f261dcfa6ea16e474187795.txt \ log-samples/sample-70c906b3c1a1cf03f15bde92ee78edfa6f9b7960.txt \ log-samples/sample-ad31f12d2adabd07e3ddda3ad5b0dbf6b49c4c99.txt nodist_noinst_DATA = \ simple-db.db TESTS = \ test_ansi_scrubber \ test_auto_fd \ test_auto_mem \ test_bookmarks \ test_date_time_scanner \ test_cmds.sh \ test_line_buffer2 \ test_line_buffer.sh \ test_listview.sh \ test_mvwattrline.sh \ test_grep_proc.sh \ test_grep_proc2 \ test_hist_source \ test_json_format.sh \ test_log_accel \ test_logfile.sh \ test_pcrepp \ test_sessions.sh \ test_sql.sh \ test_sql_coll_func.sh \ test_sql_fs_func.sh \ test_sql_str_func.sh \ test_view_colors.sh \ test_vt52_curses.sh \ test_top_status \ test_data_parser.sh \ test_yajlpp DISTCLEANFILES = \ *.dat \ *.err \ *.db \ *.dpt \ *.diff \ *.index \ *.tmp \ *.gz \ *.bz2 distclean-local: rm -rf sessions lnav-0.7.0/test/Makefile.in000664 000765 000024 00000162061 12315442600 015757 0ustar00stackstaff000000 000000 # Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ check_PROGRAMS = drive_data_scanner$(EXEEXT) \ drive_line_buffer$(EXEEXT) drive_grep_proc$(EXEEXT) \ drive_listview$(EXEEXT) drive_logfile$(EXEEXT) \ drive_mvwattrline$(EXEEXT) drive_sequencer$(EXEEXT) \ drive_sql$(EXEEXT) drive_view_colors$(EXEEXT) \ drive_vt52_curses$(EXEEXT) drive_readline_curses$(EXEEXT) \ slicer$(EXEEXT) scripty$(EXEEXT) test_ansi_scrubber$(EXEEXT) \ test_auto_fd$(EXEEXT) test_auto_mem$(EXEEXT) \ test_bookmarks$(EXEEXT) test_date_time_scanner$(EXEEXT) \ test_grep_proc2$(EXEEXT) test_hist_source$(EXEEXT) \ test_line_buffer2$(EXEEXT) test_log_accel$(EXEEXT) \ test_pcrepp$(EXEEXT) test_top_status$(EXEEXT) \ test_yajlpp$(EXEEXT) TESTS = test_ansi_scrubber$(EXEEXT) test_auto_fd$(EXEEXT) \ test_auto_mem$(EXEEXT) test_bookmarks$(EXEEXT) \ test_date_time_scanner$(EXEEXT) test_cmds.sh \ test_line_buffer2$(EXEEXT) test_line_buffer.sh \ test_listview.sh test_mvwattrline.sh test_grep_proc.sh \ test_grep_proc2$(EXEEXT) test_hist_source$(EXEEXT) \ test_json_format.sh test_log_accel$(EXEEXT) test_logfile.sh \ test_pcrepp$(EXEEXT) test_sessions.sh test_sql.sh \ test_sql_coll_func.sh test_sql_fs_func.sh test_sql_str_func.sh \ test_view_colors.sh test_vt52_curses.sh \ test_top_status$(EXEEXT) test_data_parser.sh \ test_yajlpp$(EXEEXT) subdir = test DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/mkinstalldirs $(dist_noinst_SCRIPTS) \ $(top_srcdir)/depcomp $(dist_noinst_DATA) \ $(top_srcdir)/test-driver ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/ax_sqlite3.m4 \ $(top_srcdir)/ax_with_curses.m4 $(top_srcdir)/lnav.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am_drive_data_scanner_OBJECTS = drive_data_scanner.$(OBJEXT) drive_data_scanner_OBJECTS = $(am_drive_data_scanner_OBJECTS) am__DEPENDENCIES_1 = drive_data_scanner_DEPENDENCIES = ../src/libdiag.a \ ../src/default-log-formats-json.o ../src/dump-pid-sh.o \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_drive_grep_proc_OBJECTS = drive_grep_proc.$(OBJEXT) drive_grep_proc_OBJECTS = $(am_drive_grep_proc_OBJECTS) drive_grep_proc_DEPENDENCIES = ../src/libdiag.a $(am__DEPENDENCIES_1) am_drive_line_buffer_OBJECTS = drive_line_buffer.$(OBJEXT) drive_line_buffer_OBJECTS = $(am_drive_line_buffer_OBJECTS) drive_line_buffer_DEPENDENCIES = ../src/libdiag.a \ $(am__DEPENDENCIES_1) am_drive_listview_OBJECTS = drive_listview.$(OBJEXT) drive_listview_OBJECTS = $(am_drive_listview_OBJECTS) drive_listview_DEPENDENCIES = ../src/libdiag.a $(am__DEPENDENCIES_1) am_drive_logfile_OBJECTS = drive_logfile.$(OBJEXT) drive_logfile_OBJECTS = $(am_drive_logfile_OBJECTS) drive_logfile_DEPENDENCIES = ../src/libdiag.a \ ../src/default-log-formats-json.o ../src/dump-pid-sh.o \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_drive_mvwattrline_OBJECTS = drive_mvwattrline.$(OBJEXT) drive_mvwattrline_OBJECTS = $(am_drive_mvwattrline_OBJECTS) drive_mvwattrline_DEPENDENCIES = ../src/libdiag.a \ $(am__DEPENDENCIES_1) am_drive_readline_curses_OBJECTS = drive_readline_curses.$(OBJEXT) drive_readline_curses_OBJECTS = $(am_drive_readline_curses_OBJECTS) drive_readline_curses_DEPENDENCIES = ../src/libdiag.a \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_drive_sequencer_OBJECTS = drive_sequencer.$(OBJEXT) drive_sequencer_OBJECTS = $(am_drive_sequencer_OBJECTS) drive_sequencer_DEPENDENCIES = ../src/libdiag.a $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_drive_sql_OBJECTS = drive_sql.$(OBJEXT) drive_sql_OBJECTS = $(am_drive_sql_OBJECTS) drive_sql_DEPENDENCIES = ../src/libdiag.a $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_drive_view_colors_OBJECTS = drive_view_colors.$(OBJEXT) drive_view_colors_OBJECTS = $(am_drive_view_colors_OBJECTS) drive_view_colors_DEPENDENCIES = ../src/libdiag.a \ $(am__DEPENDENCIES_1) am_drive_vt52_curses_OBJECTS = drive_vt52_curses.$(OBJEXT) drive_vt52_curses_OBJECTS = $(am_drive_vt52_curses_OBJECTS) drive_vt52_curses_DEPENDENCIES = ../src/libdiag.a \ $(am__DEPENDENCIES_1) am_scripty_OBJECTS = scripty.$(OBJEXT) scripty_OBJECTS = $(am_scripty_OBJECTS) scripty_DEPENDENCIES = ../src/libdiag.a am_slicer_OBJECTS = slicer.$(OBJEXT) slicer_OBJECTS = $(am_slicer_OBJECTS) slicer_DEPENDENCIES = ../src/libdiag.a am_test_ansi_scrubber_OBJECTS = test_ansi_scrubber.$(OBJEXT) test_ansi_scrubber_OBJECTS = $(am_test_ansi_scrubber_OBJECTS) test_ansi_scrubber_DEPENDENCIES = ../src/libdiag.a \ $(am__DEPENDENCIES_1) am_test_auto_fd_OBJECTS = test_auto_fd.$(OBJEXT) test_auto_fd_OBJECTS = $(am_test_auto_fd_OBJECTS) test_auto_fd_DEPENDENCIES = ../src/libdiag.a am_test_auto_mem_OBJECTS = test_auto_mem.$(OBJEXT) test_auto_mem_OBJECTS = $(am_test_auto_mem_OBJECTS) test_auto_mem_LDADD = $(LDADD) test_auto_mem_DEPENDENCIES = am_test_bookmarks_OBJECTS = test_bookmarks.$(OBJEXT) test_bookmarks_OBJECTS = $(am_test_bookmarks_OBJECTS) test_bookmarks_DEPENDENCIES = ../src/libdiag.a am_test_date_time_scanner_OBJECTS = test_date_time_scanner.$(OBJEXT) test_date_time_scanner_OBJECTS = $(am_test_date_time_scanner_OBJECTS) test_date_time_scanner_DEPENDENCIES = ../src/libdiag.a \ $(am__DEPENDENCIES_1) am_test_grep_proc2_OBJECTS = test_grep_proc2.$(OBJEXT) test_grep_proc2_OBJECTS = $(am_test_grep_proc2_OBJECTS) test_grep_proc2_DEPENDENCIES = ../src/libdiag.a $(am__DEPENDENCIES_1) am_test_hist_source_OBJECTS = test_hist_source.$(OBJEXT) test_hist_source_OBJECTS = $(am_test_hist_source_OBJECTS) test_hist_source_DEPENDENCIES = ../src/libdiag.a $(am__DEPENDENCIES_1) am_test_line_buffer2_OBJECTS = test_line_buffer2.$(OBJEXT) test_line_buffer2_OBJECTS = $(am_test_line_buffer2_OBJECTS) test_line_buffer2_DEPENDENCIES = ../src/libdiag.a am_test_log_accel_OBJECTS = test_log_accel.$(OBJEXT) test_log_accel_OBJECTS = $(am_test_log_accel_OBJECTS) test_log_accel_DEPENDENCIES = ../src/libdiag.a am_test_pcrepp_OBJECTS = test_pcrepp.$(OBJEXT) test_pcrepp_OBJECTS = $(am_test_pcrepp_OBJECTS) test_pcrepp_DEPENDENCIES = ../src/libdiag.a $(am__DEPENDENCIES_1) am_test_top_status_OBJECTS = test_top_status.$(OBJEXT) test_top_status_OBJECTS = $(am_test_top_status_OBJECTS) test_top_status_DEPENDENCIES = ../src/libdiag.a $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_test_yajlpp_OBJECTS = test_yajlpp.$(OBJEXT) test_yajlpp_OBJECTS = $(am_test_yajlpp_OBJECTS) test_yajlpp_DEPENDENCIES = ../src/libdiag.a SCRIPTS = $(dist_noinst_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(drive_data_scanner_SOURCES) $(drive_grep_proc_SOURCES) \ $(drive_line_buffer_SOURCES) $(drive_listview_SOURCES) \ $(drive_logfile_SOURCES) $(drive_mvwattrline_SOURCES) \ $(drive_readline_curses_SOURCES) $(drive_sequencer_SOURCES) \ $(drive_sql_SOURCES) $(drive_view_colors_SOURCES) \ $(drive_vt52_curses_SOURCES) $(scripty_SOURCES) \ $(slicer_SOURCES) $(test_ansi_scrubber_SOURCES) \ $(test_auto_fd_SOURCES) $(test_auto_mem_SOURCES) \ $(test_bookmarks_SOURCES) $(test_date_time_scanner_SOURCES) \ $(test_grep_proc2_SOURCES) $(test_hist_source_SOURCES) \ $(test_line_buffer2_SOURCES) $(test_log_accel_SOURCES) \ $(test_pcrepp_SOURCES) $(test_top_status_SOURCES) \ $(test_yajlpp_SOURCES) DIST_SOURCES = $(drive_data_scanner_SOURCES) \ $(drive_grep_proc_SOURCES) $(drive_line_buffer_SOURCES) \ $(drive_listview_SOURCES) $(drive_logfile_SOURCES) \ $(drive_mvwattrline_SOURCES) $(drive_readline_curses_SOURCES) \ $(drive_sequencer_SOURCES) $(drive_sql_SOURCES) \ $(drive_view_colors_SOURCES) $(drive_vt52_curses_SOURCES) \ $(scripty_SOURCES) $(slicer_SOURCES) \ $(test_ansi_scrubber_SOURCES) $(test_auto_fd_SOURCES) \ $(test_auto_mem_SOURCES) $(test_bookmarks_SOURCES) \ $(test_date_time_scanner_SOURCES) $(test_grep_proc2_SOURCES) \ $(test_hist_source_SOURCES) $(test_line_buffer2_SOURCES) \ $(test_log_accel_SOURCES) $(test_pcrepp_SOURCES) \ $(test_top_status_SOURCES) $(test_yajlpp_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_noinst_DATA) $(nodist_noinst_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) AM_RECURSIVE_TARGETS = check recheck TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BZIP2_CMD = @BZIP2_CMD@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CFLAGS_PG = @CFLAGS_PG@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CURSES_LIB = @CURSES_LIB@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ 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@ 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@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ READLINE_CFLAGS = @READLINE_CFLAGS@ READLINE_LIBS = @READLINE_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_CMD = @SQLITE3_CMD@ SQLITE3_LDFLAGS = @SQLITE3_LDFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ SQLITE3_VERSION = @SQLITE3_VERSION@ STATIC_LDFLAGS = @STATIC_LDFLAGS@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ abssrcdir = @abssrcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ 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@ TESTS_ENVIRONMENT = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT LOG_COMPILER = $(SHELL) $(top_builddir)/TESTS_ENVIRONMENT AM_CPPFLAGS = \ -I$(top_srcdir)/src \ $(SQLITE3_CFLAGS) AM_LDFLAGS = \ $(STATIC_LDFLAGS) \ $(SQLITE3_LDFLAGS) \ -pthread LDADD = -lz test_ansi_scrubber_SOURCES = test_ansi_scrubber.cc test_ansi_scrubber_LDADD = ../src/libdiag.a $(CURSES_LIB) test_auto_fd_SOURCES = test_auto_fd.cc test_auto_fd_LDADD = ../src/libdiag.a test_auto_mem_SOURCES = test_auto_mem.cc test_bookmarks_SOURCES = test_bookmarks.cc test_bookmarks_LDADD = ../src/libdiag.a test_date_time_scanner_SOURCES = test_date_time_scanner.cc test_date_time_scanner_LDADD = ../src/libdiag.a $(SQLITE3_LIBS) -lcrypto test_grep_proc2_SOURCES = test_grep_proc2.cc test_grep_proc2_LDADD = ../src/libdiag.a $(PCRE_LIBS) -lz test_hist_source_SOURCES = test_hist_source.cc test_hist_source_LDADD = ../src/libdiag.a $(CURSES_LIB) -lz test_line_buffer2_SOURCES = test_line_buffer2.cc test_line_buffer2_LDADD = ../src/libdiag.a test_log_accel_SOURCES = test_log_accel.cc test_log_accel_LDADD = ../src/libdiag.a test_pcrepp_SOURCES = test_pcrepp.cc test_pcrepp_LDADD = ../src/libdiag.a $(PCRE_LIBS) -lz test_top_status_SOURCES = test_top_status.cc test_top_status_LDADD = ../src/libdiag.a $(CURSES_LIB) $(PCRE_LIBS) $(SQLITE3_LIBS) -lz test_yajlpp_SOURCES = test_yajlpp.cc test_yajlpp_LDADD = ../src/libdiag.a drive_line_buffer_SOURCES = drive_line_buffer.cc drive_line_buffer_LDADD = ../src/libdiag.a $(CURSES_LIB) -lz drive_grep_proc_SOURCES = drive_grep_proc.cc drive_grep_proc_LDADD = ../src/libdiag.a $(PCRE_LIBS) -lz drive_listview_SOURCES = drive_listview.cc drive_listview_LDADD = ../src/libdiag.a $(CURSES_LIB) -lz drive_logfile_SOURCES = drive_logfile.cc drive_logfile_LDADD = \ ../src/libdiag.a \ ../src/default-log-formats-json.o \ ../src/dump-pid-sh.o \ $(CURSES_LIB) \ $(SQLITE3_LIBS) \ $(PCRE_LIBS) \ -lpcrecpp drive_sequencer_SOURCES = drive_sequencer.cc drive_sequencer_LDADD = ../src/libdiag.a $(CURSES_LIB) $(SQLITE3_LIBS) drive_data_scanner_SOURCES = \ drive_data_scanner.cc drive_data_scanner_LDADD = \ ../src/libdiag.a \ ../src/default-log-formats-json.o \ ../src/dump-pid-sh.o \ $(PCRE_LIBS) \ $(SQLITE3_LIBS) \ -lpcrecpp \ $(CURSES_LIB) drive_mvwattrline_SOURCES = drive_mvwattrline.cc drive_mvwattrline_LDADD = ../src/libdiag.a $(CURSES_LIB) drive_view_colors_SOURCES = drive_view_colors.cc drive_view_colors_LDADD = ../src/libdiag.a $(CURSES_LIB) drive_vt52_curses_SOURCES = drive_vt52_curses.cc drive_vt52_curses_LDADD = ../src/libdiag.a $(CURSES_LIB) drive_readline_curses_SOURCES = drive_readline_curses.cc drive_readline_curses_LDADD = ../src/libdiag.a $(READLINE_LIBS) $(CURSES_LIB) drive_sql_SOURCES = \ drive_sql.cc drive_sql_LDADD = \ ../src/libdiag.a \ $(SQLITE3_LIBS) \ $(PCRE_LIBS) \ $(CURSES_LIB) \ $(READLINE_LIBS) \ -lpcrecpp slicer_SOURCES = slicer.cc slicer_LDADD = ../src/libdiag.a scripty_SOURCES = scripty.cc scripty_LDADD = ../src/libdiag.a dist_noinst_SCRIPTS = \ parser_debugger.py \ test_cmds.sh \ test_data_parser.sh \ test_grep_proc.sh \ test_json_format.sh \ test_line_buffer.sh \ test_listview.sh \ test_logfile.sh \ test_mvwattrline.sh \ test_sessions.sh \ test_sql.sh \ test_sql_coll_func.sh \ test_sql_str_func.sh \ test_sql_fs_func.sh \ test_view_colors.sh \ test_vt52_curses.sh dist_noinst_DATA = \ ansi-colors.0.in \ datafile_simple.0 \ datafile_simple.1 \ datafile_simple.2 \ datafile_simple.3 \ datafile_simple.4 \ datafile_simple.5 \ datafile_simple.6 \ datafile_simple.7 \ datafile_simple.8 \ datafile_simple.9 \ datafile_simple.10 \ datafile_simple.11 \ listview_output.0 \ listview_output.1 \ listview_output.2 \ listview_output.3 \ listview_output.4 \ listview_output.5 \ listview_output.6 \ logfile_access_log.0 \ logfile_access_log.1 \ logfile_empty.0 \ logfile_generic.0 \ logfile_glog.0 \ logfile_json.json \ logfile_multiline.0 \ logfile_strace_log.0 \ logfile_syslog.0 \ logfile_syslog.1 \ logfile_tcsh_history.0 \ logfile_with_a_really_long_name_to_test_a_bug_with_long_names.0 \ mvwattrline_output.0 \ simple-db.sql \ view_colors_output.0 \ vt52_curses_input.0 \ vt52_curses_input.1 \ vt52_curses_output.0 \ vt52_curses_output.1 \ formats/jsontest/format.json \ log-samples/sample-27353a72ba4025448f261dcfa6ea16e474187795.txt \ log-samples/sample-70c906b3c1a1cf03f15bde92ee78edfa6f9b7960.txt \ log-samples/sample-ad31f12d2adabd07e3ddda3ad5b0dbf6b49c4c99.txt nodist_noinst_DATA = \ simple-db.db DISTCLEANFILES = \ *.dat \ *.err \ *.db \ *.dpt \ *.diff \ *.index \ *.tmp \ *.gz \ *.bz2 all: all-am .SUFFIXES: .SUFFIXES: .cc .log .o .obj .test .test$(EXEEXT) .trs $(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) --foreign test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-checkPROGRAMS: -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) drive_data_scanner$(EXEEXT): $(drive_data_scanner_OBJECTS) $(drive_data_scanner_DEPENDENCIES) $(EXTRA_drive_data_scanner_DEPENDENCIES) @rm -f drive_data_scanner$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_data_scanner_OBJECTS) $(drive_data_scanner_LDADD) $(LIBS) drive_grep_proc$(EXEEXT): $(drive_grep_proc_OBJECTS) $(drive_grep_proc_DEPENDENCIES) $(EXTRA_drive_grep_proc_DEPENDENCIES) @rm -f drive_grep_proc$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_grep_proc_OBJECTS) $(drive_grep_proc_LDADD) $(LIBS) drive_line_buffer$(EXEEXT): $(drive_line_buffer_OBJECTS) $(drive_line_buffer_DEPENDENCIES) $(EXTRA_drive_line_buffer_DEPENDENCIES) @rm -f drive_line_buffer$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_line_buffer_OBJECTS) $(drive_line_buffer_LDADD) $(LIBS) drive_listview$(EXEEXT): $(drive_listview_OBJECTS) $(drive_listview_DEPENDENCIES) $(EXTRA_drive_listview_DEPENDENCIES) @rm -f drive_listview$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_listview_OBJECTS) $(drive_listview_LDADD) $(LIBS) drive_logfile$(EXEEXT): $(drive_logfile_OBJECTS) $(drive_logfile_DEPENDENCIES) $(EXTRA_drive_logfile_DEPENDENCIES) @rm -f drive_logfile$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_logfile_OBJECTS) $(drive_logfile_LDADD) $(LIBS) drive_mvwattrline$(EXEEXT): $(drive_mvwattrline_OBJECTS) $(drive_mvwattrline_DEPENDENCIES) $(EXTRA_drive_mvwattrline_DEPENDENCIES) @rm -f drive_mvwattrline$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_mvwattrline_OBJECTS) $(drive_mvwattrline_LDADD) $(LIBS) drive_readline_curses$(EXEEXT): $(drive_readline_curses_OBJECTS) $(drive_readline_curses_DEPENDENCIES) $(EXTRA_drive_readline_curses_DEPENDENCIES) @rm -f drive_readline_curses$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_readline_curses_OBJECTS) $(drive_readline_curses_LDADD) $(LIBS) drive_sequencer$(EXEEXT): $(drive_sequencer_OBJECTS) $(drive_sequencer_DEPENDENCIES) $(EXTRA_drive_sequencer_DEPENDENCIES) @rm -f drive_sequencer$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_sequencer_OBJECTS) $(drive_sequencer_LDADD) $(LIBS) drive_sql$(EXEEXT): $(drive_sql_OBJECTS) $(drive_sql_DEPENDENCIES) $(EXTRA_drive_sql_DEPENDENCIES) @rm -f drive_sql$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_sql_OBJECTS) $(drive_sql_LDADD) $(LIBS) drive_view_colors$(EXEEXT): $(drive_view_colors_OBJECTS) $(drive_view_colors_DEPENDENCIES) $(EXTRA_drive_view_colors_DEPENDENCIES) @rm -f drive_view_colors$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_view_colors_OBJECTS) $(drive_view_colors_LDADD) $(LIBS) drive_vt52_curses$(EXEEXT): $(drive_vt52_curses_OBJECTS) $(drive_vt52_curses_DEPENDENCIES) $(EXTRA_drive_vt52_curses_DEPENDENCIES) @rm -f drive_vt52_curses$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(drive_vt52_curses_OBJECTS) $(drive_vt52_curses_LDADD) $(LIBS) scripty$(EXEEXT): $(scripty_OBJECTS) $(scripty_DEPENDENCIES) $(EXTRA_scripty_DEPENDENCIES) @rm -f scripty$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(scripty_OBJECTS) $(scripty_LDADD) $(LIBS) slicer$(EXEEXT): $(slicer_OBJECTS) $(slicer_DEPENDENCIES) $(EXTRA_slicer_DEPENDENCIES) @rm -f slicer$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(slicer_OBJECTS) $(slicer_LDADD) $(LIBS) test_ansi_scrubber$(EXEEXT): $(test_ansi_scrubber_OBJECTS) $(test_ansi_scrubber_DEPENDENCIES) $(EXTRA_test_ansi_scrubber_DEPENDENCIES) @rm -f test_ansi_scrubber$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_ansi_scrubber_OBJECTS) $(test_ansi_scrubber_LDADD) $(LIBS) test_auto_fd$(EXEEXT): $(test_auto_fd_OBJECTS) $(test_auto_fd_DEPENDENCIES) $(EXTRA_test_auto_fd_DEPENDENCIES) @rm -f test_auto_fd$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_auto_fd_OBJECTS) $(test_auto_fd_LDADD) $(LIBS) test_auto_mem$(EXEEXT): $(test_auto_mem_OBJECTS) $(test_auto_mem_DEPENDENCIES) $(EXTRA_test_auto_mem_DEPENDENCIES) @rm -f test_auto_mem$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_auto_mem_OBJECTS) $(test_auto_mem_LDADD) $(LIBS) test_bookmarks$(EXEEXT): $(test_bookmarks_OBJECTS) $(test_bookmarks_DEPENDENCIES) $(EXTRA_test_bookmarks_DEPENDENCIES) @rm -f test_bookmarks$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_bookmarks_OBJECTS) $(test_bookmarks_LDADD) $(LIBS) test_date_time_scanner$(EXEEXT): $(test_date_time_scanner_OBJECTS) $(test_date_time_scanner_DEPENDENCIES) $(EXTRA_test_date_time_scanner_DEPENDENCIES) @rm -f test_date_time_scanner$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_date_time_scanner_OBJECTS) $(test_date_time_scanner_LDADD) $(LIBS) test_grep_proc2$(EXEEXT): $(test_grep_proc2_OBJECTS) $(test_grep_proc2_DEPENDENCIES) $(EXTRA_test_grep_proc2_DEPENDENCIES) @rm -f test_grep_proc2$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_grep_proc2_OBJECTS) $(test_grep_proc2_LDADD) $(LIBS) test_hist_source$(EXEEXT): $(test_hist_source_OBJECTS) $(test_hist_source_DEPENDENCIES) $(EXTRA_test_hist_source_DEPENDENCIES) @rm -f test_hist_source$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_hist_source_OBJECTS) $(test_hist_source_LDADD) $(LIBS) test_line_buffer2$(EXEEXT): $(test_line_buffer2_OBJECTS) $(test_line_buffer2_DEPENDENCIES) $(EXTRA_test_line_buffer2_DEPENDENCIES) @rm -f test_line_buffer2$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_line_buffer2_OBJECTS) $(test_line_buffer2_LDADD) $(LIBS) test_log_accel$(EXEEXT): $(test_log_accel_OBJECTS) $(test_log_accel_DEPENDENCIES) $(EXTRA_test_log_accel_DEPENDENCIES) @rm -f test_log_accel$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_log_accel_OBJECTS) $(test_log_accel_LDADD) $(LIBS) test_pcrepp$(EXEEXT): $(test_pcrepp_OBJECTS) $(test_pcrepp_DEPENDENCIES) $(EXTRA_test_pcrepp_DEPENDENCIES) @rm -f test_pcrepp$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_pcrepp_OBJECTS) $(test_pcrepp_LDADD) $(LIBS) test_top_status$(EXEEXT): $(test_top_status_OBJECTS) $(test_top_status_DEPENDENCIES) $(EXTRA_test_top_status_DEPENDENCIES) @rm -f test_top_status$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_top_status_OBJECTS) $(test_top_status_LDADD) $(LIBS) test_yajlpp$(EXEEXT): $(test_yajlpp_OBJECTS) $(test_yajlpp_DEPENDENCIES) $(EXTRA_test_yajlpp_DEPENDENCIES) @rm -f test_yajlpp$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(test_yajlpp_OBJECTS) $(test_yajlpp_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_data_scanner.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_grep_proc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_line_buffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_listview.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_logfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_mvwattrline.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_readline_curses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_sequencer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_sql.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_view_colors.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drive_vt52_curses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scripty.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slicer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_ansi_scrubber.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_auto_fd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_auto_mem.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_bookmarks.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_date_time_scanner.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_grep_proc2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_hist_source.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_line_buffer2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_log_accel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_pcrepp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_top_status.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_yajlpp.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ else \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all $(check_PROGRAMS) @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? test_ansi_scrubber.log: test_ansi_scrubber$(EXEEXT) @p='test_ansi_scrubber$(EXEEXT)'; \ b='test_ansi_scrubber'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_auto_fd.log: test_auto_fd$(EXEEXT) @p='test_auto_fd$(EXEEXT)'; \ b='test_auto_fd'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_auto_mem.log: test_auto_mem$(EXEEXT) @p='test_auto_mem$(EXEEXT)'; \ b='test_auto_mem'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_bookmarks.log: test_bookmarks$(EXEEXT) @p='test_bookmarks$(EXEEXT)'; \ b='test_bookmarks'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_date_time_scanner.log: test_date_time_scanner$(EXEEXT) @p='test_date_time_scanner$(EXEEXT)'; \ b='test_date_time_scanner'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_cmds.sh.log: test_cmds.sh @p='test_cmds.sh'; \ b='test_cmds.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_line_buffer2.log: test_line_buffer2$(EXEEXT) @p='test_line_buffer2$(EXEEXT)'; \ b='test_line_buffer2'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_line_buffer.sh.log: test_line_buffer.sh @p='test_line_buffer.sh'; \ b='test_line_buffer.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_listview.sh.log: test_listview.sh @p='test_listview.sh'; \ b='test_listview.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_mvwattrline.sh.log: test_mvwattrline.sh @p='test_mvwattrline.sh'; \ b='test_mvwattrline.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_grep_proc.sh.log: test_grep_proc.sh @p='test_grep_proc.sh'; \ b='test_grep_proc.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_grep_proc2.log: test_grep_proc2$(EXEEXT) @p='test_grep_proc2$(EXEEXT)'; \ b='test_grep_proc2'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_hist_source.log: test_hist_source$(EXEEXT) @p='test_hist_source$(EXEEXT)'; \ b='test_hist_source'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_json_format.sh.log: test_json_format.sh @p='test_json_format.sh'; \ b='test_json_format.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_log_accel.log: test_log_accel$(EXEEXT) @p='test_log_accel$(EXEEXT)'; \ b='test_log_accel'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_logfile.sh.log: test_logfile.sh @p='test_logfile.sh'; \ b='test_logfile.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_pcrepp.log: test_pcrepp$(EXEEXT) @p='test_pcrepp$(EXEEXT)'; \ b='test_pcrepp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_sessions.sh.log: test_sessions.sh @p='test_sessions.sh'; \ b='test_sessions.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_sql.sh.log: test_sql.sh @p='test_sql.sh'; \ b='test_sql.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_sql_coll_func.sh.log: test_sql_coll_func.sh @p='test_sql_coll_func.sh'; \ b='test_sql_coll_func.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_sql_fs_func.sh.log: test_sql_fs_func.sh @p='test_sql_fs_func.sh'; \ b='test_sql_fs_func.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_sql_str_func.sh.log: test_sql_str_func.sh @p='test_sql_str_func.sh'; \ b='test_sql_str_func.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_view_colors.sh.log: test_view_colors.sh @p='test_view_colors.sh'; \ b='test_view_colors.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_vt52_curses.sh.log: test_vt52_curses.sh @p='test_vt52_curses.sh'; \ b='test_vt52_curses.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_top_status.log: test_top_status$(EXEEXT) @p='test_top_status$(EXEEXT)'; \ b='test_top_status'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_data_parser.sh.log: test_data_parser.sh @p='test_data_parser.sh'; \ b='test_data_parser.sh'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) test_yajlpp.log: test_yajlpp$(EXEEXT) @p='test_yajlpp$(EXEEXT)'; \ b='test_yajlpp'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(SCRIPTS) $(DATA) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-local 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: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic distclean-local \ 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 \ recheck tags tags-am uninstall uninstall-am simple-db.db: simple-db.sql rm -f $@ $(SQLITE3_CMD) $@ < $(srcdir)/simple-db.sql distclean-local: rm -rf sessions # 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: lnav-0.7.0/test/mvwattrline_output.0000664 000765 000024 00000011606 12306615221 017766 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b6d1b5b6d1b5b33376d1b5b34306d1b5b313b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b323b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b333b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b343b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b353b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b363b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b373b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b383b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b393b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31303b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31313b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31323b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31333b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31343b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31353b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31363b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31373b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31383b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31393b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32303b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32313b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32323b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32333b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32343b3148202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200820081b5b3468201b5b346c1b5b481b5b33376d1b5b34306d506c61696e20746578742020202020202020202020202020202020202020202020202020202020200d0a1b5b376d20202020202020201b5b6d1b5b33376d1b5b34306d4c656164696e67207461622020202020202020202020202020202020202020200d0a541b5b376d616220202020201b5b6d1b5b33376d1b5b34306d77697468207465787420202020202020202020202020202020202020202020200d0a5461621b5b376d20202020201b5b6d1b5b33376d1b5b34306d77697468207465787420233220202020202020202020202020202020202020200d0a54657874201b5b33316d1b5b34306d77691b5b376d74681b5b33376d1b5b34306d206d691b5b6d1b5b33376d1b5b34306d78656420617474726962757465732e202020202020202020202020200d0a1b5b6d1b5b6d1b5b33376d1b5b34306d1b5b6d1b5b3138421b5b4b1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e lnav-0.7.0/test/parser_debugger.py000775 000765 000024 00000013624 12211635055 017432 0ustar00stackstaff000000 000000 #! /usr/bin/env python # Copyright (c) 2013, Timothy Stack # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of Timothy Stack nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import os import json import string import readline import itertools import collections TEST_DIR = os.path.dirname(__file__) ROOT_DIR = os.path.dirname(TEST_DIR) SRC_DIR = os.path.join(ROOT_DIR, "src") addr_to_name = {} name_to_addr = {} element_lists = collections.defaultdict(list) breakpoints = set() def completer(text, state): options = [x for x in itertools.chain(name_to_addr, element_lists, breakpoints) if x.startswith(text)] try: return options[state] except IndexError: return None readline.set_completer(completer) if 'libedit' in readline.__doc__: readline.parse_and_bind('bind ^I rl_complete') else: readline.parse_and_bind('tab: complete') input_line = '' ops = [] for line in open("scanned.dpt"): if line.startswith("input "): input_line = line[6:-1] else: ops.append(map(string.strip, line.split())) def getstr(capture): start, end = capture.split(':') return input_line[int(start):int(end)] def printlist(name_or_addr): if name_or_addr in name_to_addr: print "(%s) %s" % (name_or_addr, element_lists[name_to_addr[name_or_addr]]) elif name_or_addr in element_lists: print "(%s) %s" % (addr_to_name.get(name_or_addr, name_or_addr), element_lists[name_or_addr]) else: print "error: unknown list --", name_or_addr def handleop(fields): addr = fields[0] loc = fields[1].split(':') method_name = fields[2] method_args = fields[3:] if addr == '0x0': el = None else: el = element_lists[addr] if method_name == 'element_list_t': addr_to_name[addr] = method_args[0] name_to_addr[method_args[0]] = addr elif method_name == '~element_list_t': pass elif method_name == 'push_back': el.append((method_args[0], getstr(method_args[1]))) elif method_name == 'pop_front': el.pop(0) elif method_name == 'pop_back': el.pop() elif method_name == 'splice': pos = int(method_args[0]) other = element_lists[method_args[1]] start, from_end = map(int, method_args[2].split(':')) end = len(other) - from_end sub_list = other[start:end] del other[start:end] el[pos:pos] = sub_list elif method_name == 'point': breakpoints.add(method_args[0]) else: print "Unhandled method: ", method_name def playupto(length): addr_to_name.clear() name_to_addr.clear() element_lists.clear() for index in range(length): handleop(ops[index]) def find_prev_point(start, name): orig_start = start while start > 0: start -= 1; fields = ops[start] if fields[2] != 'point': continue if not name or fields[3] == name: return start + 1 return orig_start + 1 def find_next_point(start, name): orig_start = start while start < len(ops): start += 1; fields = ops[start] if fields[2] != 'point': continue if not name or fields[3] == name: return start + 1 return orig_start + 1 index = len(ops) last_cmd = [''] watch_list = set() while True: playupto(index) if index == 0: print "init" else: print "#%s %s" % (index -1, ops[index - 1]) for list_name in watch_list: printlist(list_name) try: cmd = raw_input("> ").split() except EOFError: print break if not cmd or cmd[0] == '': cmd = last_cmd if not cmd or cmd[0] == '': pass elif cmd[0] == 'q': break elif cmd[0] == 'n': if index < len(ops): index += 1 elif cmd[0] == 'r': if index > 0: index -= 1 elif cmd[0] == 'b': if len(cmd) == 1: cmd.append('') index = find_prev_point(index - 1, cmd[1]) elif cmd[0] == 'c': if len(cmd) == 1: cmd.append('') index = find_next_point(index - 1, cmd[1]) elif cmd[0] == 'p': if len(cmd) > 1: printlist(cmd[1]) else: print input_line for addr in element_lists: printlist(addr) elif cmd[0] == 'w': watch_list.add(cmd[1]) elif cmd[0] == 'u': watch_list.remove(cmd[1]) else: print "error: unknown command --", cmd last_cmd = cmd lnav-0.7.0/test/scripty.cc000664 000765 000024 00000040376 12306075241 015725 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined HAVE_NCURSESW_CURSES_H # include #elif defined HAVE_NCURSESW_H # include #elif defined HAVE_NCURSES_CURSES_H # include #elif defined HAVE_NCURSES_H # include #elif defined HAVE_CURSES_H # include #else # error "SysV or X/Open-compatible Curses header file required" #endif #ifdef HAVE_PTY_H #include #endif #ifdef HAVE_UTIL_H #include #endif #ifdef HAVE_LIBUTIL_H #include #endif #include #include #include "auto_fd.hh" using namespace std; /** * An RAII class for opening a PTY and forking a child process. */ class child_term { public: class error : public std::exception { public: error(int err) : e_err(err) { }; int e_err; }; child_term() { struct winsize ws; auto_fd slave; memset(&ws, 0, sizeof(ws)); if (isatty(STDIN_FILENO) && tcgetattr(STDIN_FILENO, &this->ct_termios) == -1) { throw error(errno); } if (isatty(STDOUT_FILENO) && ioctl(STDOUT_FILENO, TIOCGWINSZ, &this->ct_winsize) == -1) { throw error(errno); } ws.ws_col = 80; ws.ws_row = 24; if (openpty(this->ct_master.out(), slave.out(), NULL, NULL, &ws) < 0) { throw error(errno); } if ((this->ct_child = fork()) == -1) throw error(errno); if (this->ct_child == 0) { this->ct_master.reset(); dup2(slave, STDIN_FILENO); dup2(slave, STDOUT_FILENO); setenv("TERM", "xterm-color", 1); } else { slave.reset(); } }; virtual ~child_term() { (void)this->wait_for_child(); if (isatty(STDIN_FILENO) && tcsetattr(STDIN_FILENO, TCSANOW, &this->ct_termios) == -1) { perror("tcsetattr"); } if (isatty(STDOUT_FILENO) && ioctl(STDOUT_FILENO, TIOCSWINSZ, &this->ct_winsize) == -1) { perror("ioctl"); } }; int wait_for_child(void) { int retval = -1; if (this->ct_child > 0) { kill(this->ct_child, SIGTERM); this->ct_child = -1; while (wait(&retval) < 0 && (errno == EINTR)); } return retval; }; bool is_child() { return this->ct_child == 0; }; pid_t get_child_pid() { return this->ct_child; }; int get_fd() { return this->ct_master; }; protected: pid_t ct_child; auto_fd ct_master; struct termios ct_termios; struct winsize ct_winsize; }; /** * @param fd The file descriptor to switch to raw mode. * @return Zero on success, -1 on error. */ static int tty_raw(int fd) { struct termios attr[1]; assert(fd >= 0); if (tcgetattr(fd, attr) == -1) return -1; attr->c_lflag &= ~(ECHO | ICANON | IEXTEN); attr->c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON); attr->c_cflag &= ~(CSIZE | PARENB); attr->c_cflag |= (CS8); attr->c_oflag &= ~(OPOST); attr->c_cc[VMIN] = 1; attr->c_cc[VTIME] = 0; return tcsetattr(fd, TCSANOW, attr); } static void dump_memory(FILE *dst, const char *src, int len) { int lpc; for (lpc = 0; lpc < len; lpc++) { fprintf(dst, "%02x", src[lpc]); } } static char *hex2bits(const char *src) { int len, pos = sizeof(int); char *retval; len = strlen(src) / 2; retval = new char[sizeof(uint32_t) + len]; *((uint32_t *)retval) = len; while (pos < (sizeof(uint32_t) + len)) { int val; sscanf(src, "%2x", &val); src += 2; retval[pos] = (char)val; pos += 1; } return retval; } typedef enum { ET_NONE, ET_READ, } expect_type_t; struct expect_read { uint32_t er_length; char er_data[]; }; struct expect { expect_type_t e_type; union { struct expect_read *read; } e_arg; }; struct expect_read_state { uint32_t ers_pos; }; class expect_handler { public: expect_handler() { memset(&this->eh_state, 0, sizeof(this->eh_state)); }; int process_input(const char *buffer, size_t blen) { if (this->eh_queue.empty()) return 0; uint32_t &exp_pos = this->eh_state.es_read.ers_pos; struct expect &next = this->eh_queue.front(); int cmp_len = min((next.e_arg.read->er_length - exp_pos), (uint32_t)blen); char *exp_start = &next.e_arg.read->er_data[this->eh_state.es_read.ers_pos]; int retval = 0; assert(buffer != NULL || blen == 0); if (memcmp(exp_start, buffer, cmp_len) == 0) { exp_pos += cmp_len; if (exp_pos == next.e_arg.read->er_length) { retval = 1; if (!this->eh_queue.empty()) { exp_pos = 0; this->eh_queue.pop(); } } } else { printf("Detected output differences at offset %d, " "expecting:\n ", exp_pos); dump_memory(stdout, exp_start, cmp_len); printf("\nGot:\n "); dump_memory(stdout, buffer, cmp_len); retval = -1; } fprintf(stderr, "pi ret %d\n", retval); return retval; }; queue eh_queue; private: union { struct expect_read_state es_read; } eh_state; }; typedef enum { CT_SLEEP, CT_WRITE, } command_type_t; struct command { command_type_t c_type; union { char *b; } c_arg; }; static struct { const char *sd_program_name; sig_atomic_t sd_looping; pid_t sd_child_pid; const char *sd_to_child_name; FILE *sd_to_child; const char *sd_from_child_name; FILE *sd_from_child; queue sd_replay; bool sd_user_step; } scripty_data; static void sigchld(int sig) { } static void sigpass(int sig) { kill(scripty_data.sd_child_pid, sig); } static void usage(void) { const char *usage_msg = "usage: %s [-h] [-t to_child] [-f from_child] -- \n" "\n" "Recorder for TTY I/O from a child process." "\n" "Options:\n" " -h Print this message, then exit.\n" " -t The file where any input sent to the child process\n" " should be stored.\n" " -f The file where any output from the child process\n" " should be stored.\n" " -r The file containing the input to be sent to the child\n" " process.\n" " -e The file containing the expected output from the child\n" " process.\n" "\n" "Examples:\n" " To record a session for playback later:\n" " $ scripty -t input.0 -f output.0 -- myCursesApp\n" "\n" " To replay the recorded session:\n" " $ scripty -r input.0 -- myCursesApp\n"; fprintf(stderr, usage_msg, scripty_data.sd_program_name); } int main(int argc, char *argv[]) { int c, fd, retval = EXIT_SUCCESS; expect_handler ex_handler; bool passout = true; FILE *file; scripty_data.sd_program_name = argv[0]; scripty_data.sd_looping = true; while ((c = getopt(argc, argv, "ht:f:r:e:ns")) != -1) { switch (c) { case 'h': usage(); exit(retval); break; case 's': scripty_data.sd_user_step = true; break; case 't': scripty_data.sd_to_child_name = optarg; break; case 'f': scripty_data.sd_from_child_name = optarg; break; case 'e': if ((file = fopen(optarg, "r")) == NULL) { fprintf(stderr, "error: cannot open %s\n", optarg); retval = EXIT_FAILURE; } else { char line[32 * 1024]; while (fgets(line, sizeof(line), file)) { char *sp; if (line[0] == '#' || (sp = strchr(line, ' ')) == NULL) { } else { struct expect exp; *sp = '\0'; sp += 1; if (strcmp(line, "read") == 0) { exp.e_type = ET_READ; exp.e_arg.read = (struct expect_read *)hex2bits(sp); } else { fprintf(stderr, "error: unknown command -- %s\n", line); retval = EXIT_FAILURE; } ex_handler.eh_queue.push(exp); } } fclose(file); file = NULL; } break; case 'r': if ((file = fopen(optarg, "r")) == NULL) { fprintf(stderr, "error: cannot open %s\n", optarg); retval = EXIT_FAILURE; } else { char line[32 * 1024]; while (fgets(line, sizeof(line), file)) { char *sp; if (line[0] == '#' || (sp = strchr(line, ' ')) == NULL) { } else { struct command cmd; *sp = '\0'; sp += 1; if (strcmp(line, "sleep") == 0) { cmd.c_type = CT_SLEEP; } else if (strcmp(line, "write") == 0) { cmd.c_type = CT_WRITE; cmd.c_arg.b = hex2bits(sp); scripty_data.sd_replay.push(cmd); } else { fprintf(stderr, "error: unknown command -- %s\n", line); retval = EXIT_FAILURE; } } } fclose(file); file = NULL; } break; case 'n': passout = false; break; default: retval = EXIT_FAILURE; break; } } argc -= optind; argv += optind; if ((scripty_data.sd_to_child_name != NULL) && (scripty_data.sd_to_child = fopen(scripty_data.sd_to_child_name, "w")) == NULL) { fprintf(stderr, "error: unable to open %s -- %s\n", scripty_data.sd_to_child_name, strerror(errno)); retval = EXIT_FAILURE; } if (scripty_data.sd_from_child_name != NULL) { if (strcmp(scripty_data.sd_from_child_name, "-") == 0) { scripty_data.sd_from_child = stdout; } else if ((scripty_data.sd_from_child = fopen(scripty_data.sd_from_child_name, "w")) == NULL) { fprintf(stderr, "error: unable from open %s -- %s\n", scripty_data.sd_from_child_name, strerror(errno)); retval = EXIT_FAILURE; } } fd = open("/tmp/scripty.err", O_WRONLY|O_CREAT|O_APPEND, 0666); dup2(fd, STDERR_FILENO); close(fd); fprintf(stderr, "startup\n"); if (scripty_data.sd_to_child != NULL) fcntl(fileno(scripty_data.sd_to_child), F_SETFD, 1); if (scripty_data.sd_from_child != NULL) fcntl(fileno(scripty_data.sd_from_child), F_SETFD, 1); if (retval != EXIT_FAILURE) { child_term ct; if (ct.is_child()) { execvp(argv[0], argv); perror("execvp"); exit(-1); } else { int maxfd, out_len = 0; bool got_expected = true; bool got_user_step; struct timeval last, now; char out_buffer[8192]; fd_set read_fds; scripty_data.sd_child_pid = ct.get_child_pid(); signal(SIGINT, sigpass); signal(SIGTERM, sigpass); signal(SIGCHLD, sigchld); gettimeofday(&now, NULL); last = now; FD_ZERO(&read_fds); FD_SET(STDIN_FILENO, &read_fds); FD_SET(ct.get_fd(), &read_fds); fprintf(stderr, "goin in the loop\n"); tty_raw(STDIN_FILENO); if (!ex_handler.eh_queue.empty()) { got_expected = false; } maxfd = max(STDIN_FILENO, ct.get_fd()); while (scripty_data.sd_looping) { fd_set ready_rfds = read_fds; struct timeval diff, to; int rc; to.tv_sec = 0; to.tv_usec = 10000; rc = select(maxfd + 1, &ready_rfds, NULL, NULL, &to); if (rc == 0) { if (!got_expected) { switch (ex_handler.process_input(NULL, 0)) { case -1: scripty_data.sd_looping = false; retval = EXIT_FAILURE; break; case 0: break; case 1: got_expected = true; break; } } if (!scripty_data.sd_replay.empty() && got_expected && (!scripty_data.sd_user_step || got_user_step)) { struct command cmd = scripty_data.sd_replay.front(); int len; fprintf(stderr, " us %d got %d\n", scripty_data.sd_user_step, got_user_step); scripty_data.sd_replay.pop(); fprintf(stderr, "replay %zd\n", scripty_data.sd_replay.size()); switch (cmd.c_type) { case CT_SLEEP: break; case CT_WRITE: len = *((int *)cmd.c_arg.b); write(ct.get_fd(), cmd.c_arg.b + sizeof(int), len); delete [] cmd.c_arg.b; break; } got_user_step = false; got_expected = false; } } else if (rc < 0) { switch (errno) { case EINTR: break; default: fprintf(stderr, "select %s\n", strerror(errno)); scripty_data.sd_looping = false; break; } } else { char buffer[1024]; fprintf(stderr, "fds ready %d\n", rc); gettimeofday(&now, NULL); timersub(&now, &last, &diff); if (FD_ISSET(STDIN_FILENO, &ready_rfds)) { rc = read(STDIN_FILENO, buffer, sizeof(buffer)); if (rc < 0) { scripty_data.sd_looping = false; } else if (rc == 0) { FD_CLR(STDIN_FILENO, &read_fds); } else if (!scripty_data.sd_replay.empty()) { if (scripty_data.sd_user_step) { got_user_step = true; } } else { write(ct.get_fd(), buffer, rc); if (scripty_data.sd_to_child != NULL) { fprintf(scripty_data.sd_to_child, "sleep %ld.%06d\n" "write ", diff.tv_sec, diff.tv_usec); dump_memory(scripty_data.sd_to_child, buffer, rc); fprintf(scripty_data.sd_to_child, "\n"); } if (scripty_data.sd_from_child != NULL) { fprintf(stderr, "do write %d\n", out_len); fprintf(scripty_data.sd_from_child, "read "); dump_memory(scripty_data.sd_from_child, out_buffer, out_len); fprintf(scripty_data.sd_from_child, "\n"); fprintf(scripty_data.sd_from_child, "# write "); dump_memory(scripty_data.sd_from_child, buffer, rc); fprintf(scripty_data.sd_from_child, "\n"); out_len = 0; } } } if (FD_ISSET(ct.get_fd(), &ready_rfds)) { rc = read(ct.get_fd(), buffer, sizeof(buffer)); fprintf(stderr, "read rc %d\n", rc); if (rc <= 0) { scripty_data.sd_looping = false; if (scripty_data.sd_from_child) { fprintf(scripty_data.sd_from_child, "read "); dump_memory(scripty_data.sd_from_child, out_buffer, out_len); fprintf(scripty_data.sd_from_child, "\n"); out_len = 0; } } else { if (passout) write(STDOUT_FILENO, buffer, rc); if (scripty_data.sd_from_child != NULL) { fprintf(stderr, "got out %d\n", rc); memcpy(&out_buffer[out_len], buffer, rc); out_len += rc; } switch (ex_handler.process_input(buffer, rc)) { case -1: scripty_data.sd_looping = false; retval = EXIT_FAILURE; break; case 0: break; case 1: got_expected = true; break; } } } } last = now; } } if (!ex_handler.eh_queue.empty()) { fprintf(stderr, "More input expected from child\n"); retval = EXIT_FAILURE; } retval = ct.wait_for_child() || retval; } if (scripty_data.sd_to_child != NULL) { fclose(scripty_data.sd_to_child); scripty_data.sd_to_child = NULL; } if (scripty_data.sd_from_child != NULL) { fclose(scripty_data.sd_from_child); scripty_data.sd_from_child = NULL; } return retval; } lnav-0.7.0/test/simple-db.sql000664 000765 000024 00000000461 12211635055 016305 0ustar00stackstaff000000 000000 CREATE TABLE IF NOT EXISTS person ( id integer PRIMARY KEY, first_name text, last_name text, age integer ); INSERT INTO person (id, first_name, last_name, age) VALUES (0, "Phil", "Myman", 30); INSERT INTO person (id, first_name, last_name, age) VALUES (1, "Lem", "Hewitt", 35); lnav-0.7.0/test/slicer.cc000664 000765 000024 00000005157 12311035743 015506 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include "line_buffer.hh" using namespace std; int main(int argc, char *argv[]) { int retval = EXIT_SUCCESS; vector index; auto_fd fd; if (argc < 2) { fprintf(stderr, "error: expecting file argument\n"); retval = EXIT_FAILURE; } else if ((fd = open(argv[1], O_RDONLY)) == -1) { perror("open"); retval = EXIT_FAILURE; } else { int line_number, start, end; off_t offset = 0; line_buffer lb; line_value lv; lb.set_fd(fd); index.push_back(offset); while (lb.read_line(offset, lv)) { index.push_back(offset); } index.pop_back(); try { while (scanf("%d:%d:%d", &line_number, &start, &end) == 3) { string str; offset = index[line_number]; lb.read_line(offset, lv); str = string(lv.lv_start, lv.lv_len); str = str.substr(start, end); printf("%s\n", str.c_str()); } } catch (line_buffer::error &e) { fprintf(stderr, "error: line buffer %s\n", strerror(e.e_err)); } } return retval; } lnav-0.7.0/test/test_ansi_scrubber.cc000664 000765 000024 00000005134 12306075226 020104 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file test_ansi_scrubber.cc * * Test for the scrub_ansi_string function. * * TODO: Add a test for the ansi-colors.0.in file. It has a matrix of all the * color/style combinations. */ #include "config.h" #include #include "ansi_scrubber.hh" using namespace std; int main(int argc, char *argv[]) { view_colors &vc = view_colors::singleton(); string_attrs_t::iterator iter; string_attrs_t sa; string str_cp; str_cp = "Hello, World!"; scrub_ansi_string(str_cp, sa); assert(str_cp == "Hello, World!"); assert(sa.empty()); str_cp = "Hello\x1b[44;m, \x1b[33;mWorld\x1b[0;m!"; scrub_ansi_string(str_cp, sa); assert(str_cp == "Hello, World!"); assert(sa[0].sa_range.lr_start == 5); assert(sa[0].sa_range.lr_end == 7); assert(sa[0].sa_type == &view_curses::VC_STYLE); assert(sa[0].sa_value.sav_int == vc.ansi_color_pair(0, 4)); assert(sa[1].sa_range.lr_start == 7); assert(sa[1].sa_range.lr_end == 12); assert(sa[1].sa_type == &view_curses::VC_STYLE); assert(sa[1].sa_value.sav_int == vc.ansi_color_pair(3, 0)); } lnav-0.7.0/test/test_auto_fd.cc000664 000765 000024 00000005047 12211635055 016704 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include "auto_fd.hh" int main(int argc, char *argv[]) { int retval = EXIT_SUCCESS; auto_fd fd1, fd2; int tmp; assert(fd1 == -1); tmp = open("/dev/null", O_RDONLY); assert(tmp != -1); fd1 = tmp; fd1 = tmp; assert(fcntl(tmp, F_GETFL) >= 0); fd1 = fd2; assert(fcntl(tmp, F_GETFL) == -1); assert(errno == EBADF); assert(fd1 == -1); tmp = open("/dev/null", O_RDONLY); assert(tmp != -1); fd1 = tmp; *fd1.out() = STDOUT_FILENO; assert(fcntl(tmp, F_GETFL) == -1); assert(errno == EBADF); { auto_fd fd_cp(const_cast(fd1)); assert(fd1 == STDOUT_FILENO); assert(fd_cp != STDOUT_FILENO); assert(fd_cp != -1); tmp = (int)fd_cp; } { auto_fd fd_cp(const_cast(fd1)); assert(fd_cp == tmp); } assert(fd1.release() == STDOUT_FILENO); assert(fd1 == -1); return retval; } lnav-0.7.0/test/test_auto_mem.cc000664 000765 000024 00000005044 12211635055 017066 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include "auto_mem.hh" struct my_data { int dummy1; int dummy2; }; int free_count; void *last_free; void my_free(void *mem) { free_count += 1; last_free = mem; } int main(int argc, char *argv[]) { int retval = EXIT_SUCCESS; auto_mem md1, md2; struct my_data md1_val, md2_val; md1 = &md1_val; assert(free_count == 0); md1 = md2; assert(free_count == 1); assert(last_free == &md1_val); assert(md1 == NULL); md1 = &md2_val; assert(free_count == 1); assert(last_free == &md1_val); *md1.out() = &md1_val; assert(free_count == 2); assert(last_free == &md2_val); assert(md1.in() == &md1_val); { auto_mem md_cp(md1); assert(md1 == NULL); assert(free_count == 2); assert(md_cp == &md1_val); } assert(free_count == 3); assert(last_free == &md1_val); return retval; } lnav-0.7.0/test/test_bookmarks.cc000664 000765 000024 00000007045 12211635055 017253 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include "bookmarks.hh" int main(int argc, char *argv[]) { int lpc, retval = EXIT_SUCCESS; bookmark_vector bv, bv_cp; bv.insert_once(vis_line_t(1)); bv.insert_once(vis_line_t(1)); assert(bv.size() == 1); bv.insert_once(vis_line_t(3)); bv.insert_once(vis_line_t(2)); assert(bv[0] == 1); assert(bv[1] == 2); assert(bv[2] == 3); bv.clear(); assert(bv.next(vis_line_t(0)) == -1); assert(bv.prev(vis_line_t(0)) == -1); assert(bv.next(vis_line_t(100)) == -1); assert(bv.prev(vis_line_t(100)) == -1); bv.insert_once(vis_line_t(2)); assert(bv.next(vis_line_t(0)) == 2); assert(bv.next(vis_line_t(2)) == -1); assert(bv.next(vis_line_t(3)) == -1); assert(bv.prev(vis_line_t(3)) == 2); assert(bv.prev(vis_line_t(2)) == -1); bv.insert_once(vis_line_t(4)); assert(bv.next(vis_line_t(0)) == 2); assert(bv.next(vis_line_t(2)) == 4); assert(bv.next(vis_line_t(3)) == 4); assert(bv.next(vis_line_t(4)) == -1); assert(bv.prev(vis_line_t(10)) == 4); assert(bv.prev(vis_line_t(5)) == 4); assert(bv.prev(vis_line_t(4)) == 2); assert(bv.prev(vis_line_t(2)) == -1); bv.clear(); const int LINE_COUNT = 10000; for (lpc = 0; lpc < 1000; lpc++) { bv.insert_once(vis_line_t(random() % LINE_COUNT)); } bv_cp = bv; sort(bv_cp.begin(), bv_cp.end()); assert(equal(bv.begin(), bv.end(), bv_cp.begin())); unique(bv_cp.begin(), bv_cp.end()); assert(equal(bv.begin(), bv.end(), bv_cp.begin())); { vis_line_t last_line(-1); for (lpc = 0; lpc != -1; lpc = bv.next(vis_line_t(lpc))) { assert(lpc >= 0); assert(lpc < LINE_COUNT); assert(last_line < lpc); last_line = vis_line_t(lpc); } last_line = vis_line_t(10000); for (lpc = LINE_COUNT - 1; lpc != -1; lpc = bv.prev(vis_line_t(lpc))) { assert(lpc >= 0); assert(lpc < LINE_COUNT); assert(last_line > lpc); last_line = vis_line_t(lpc); } } return retval; } lnav-0.7.0/test/test_cmds.sh000664 000765 000024 00000013100 12311271346 016223 0ustar00stackstaff000000 000000 #! /bin/bash lnav_test="${top_builddir}/src/lnav-test" run_test ${lnav_test} -n \ -c ":adjust-log-time 2010-01-01T00:00:00" \ ${test_dir}/logfile_access_log.0 check_output "adjust-log-time is not working" < #include #include "lnav_util.hh" static const char *BAD_TIMES[] = { "1-2-3 1:2:3", "2013-2-3 1:2:3", "2013-02-3 1:2:3", "2013-02-03 1:2:3", "2013-02-03 01:2:3", "2013-22-01 12:01:22", "2013-00-01 12:01:22", "2013-12-32 12:01:22", "2013-12-00 12:01:22", NULL }; int main(int argc, char *argv[]) { for (int lpc = 0; BAD_TIMES[lpc]; lpc++) { date_time_scanner dts; struct timeval tv; struct tm tm; assert(dts.scan(BAD_TIMES[lpc], NULL, &tm, tv) == NULL); } { const char *en_date = "Jan 1 12:00:00"; const char *bg_date = "Ene 1 12:00:00"; struct timeval en_tv, es_tv; struct tm en_tm, es_tm; date_time_scanner dts; if (setlocale(LC_TIME, "es_ES.utf8") != NULL) { assert(dts.scan(en_date, NULL, &en_tm, en_tv) != NULL); assert(dts.scan(bg_date, NULL, &es_tm, es_tv) != NULL); } } } lnav-0.7.0/test/test_grep_proc.sh000664 000765 000024 00000001511 12304743527 017267 0ustar00stackstaff000000 000000 #! /bin/bash cat > gp.dat </dev/null } run_test grep_slice 'Hello' gp.dat check_output "grep_proc didn't find the right match?" < #include #include #include #include #include "grep_proc.hh" using namespace std; static struct { int l_number; const char *l_value; } MS_LINES[] = { { 10, "" }, { 11, "" }, { 12, "" }, { 13, "" }, { 0, "" }, { 1, "" }, { 2, "" }, }; class my_source : public grep_proc_source { public: my_source() : ms_current_line(0) { }; bool grep_value_for_line(int line_number, string &value_out) { bool retval = true; assert(line_number == MS_LINES[this->ms_current_line].l_number); value_out = MS_LINES[this->ms_current_line].l_value; this->ms_current_line += 1; return retval; }; int ms_current_line; }; class my_sleeper_source : public grep_proc_source { bool grep_value_for_line(int line_number, string &value_out) { sleep(1000); return true; }; }; class my_sink : public grep_proc_sink { public: my_sink() : ms_finished(false) { }; void grep_match(grep_proc &gp, grep_line_t line, int start, int end) { }; void grep_end(grep_proc &gp) { this->ms_finished = true; }; bool ms_finished; }; static fd_set READFDS; static int MAXFD; static void looper(grep_proc &gp) { my_sink msink; gp.set_sink(&msink); while (!msink.ms_finished) { fd_set rfds = READFDS; select(MAXFD + 1, &rfds, NULL, NULL, NULL); gp.check_fd_set(rfds); } } int main(int argc, char *argv[]) { int eoff, retval = EXIT_SUCCESS; const char *errptr; pcre *code; FD_ZERO(&READFDS); code = pcre_compile("foobar", PCRE_CASELESS, &errptr, &eoff, NULL); pcre_refcount(code, 1); assert(code != NULL); { my_source ms; grep_proc gp(code, ms, MAXFD, READFDS); gp.queue_request(grep_line_t(10), grep_line_t(14)); gp.queue_request(grep_line_t(0), grep_line_t(3)); gp.start(); looper(gp); } { my_sleeper_source mss; grep_proc *gp = new grep_proc(code, mss, MAXFD, READFDS); int status; gp->queue_request(); gp->start(); assert(wait3(&status, WNOHANG, NULL) == 0); delete gp; assert(wait(&status) == -1); assert(errno == ECHILD); } free(code); return retval; } lnav-0.7.0/test/test_hist_source.cc000664 000765 000024 00000003601 12211635055 017604 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include "hist_source.hh" int main(int argc, char *argv[]) { int retval = EXIT_SUCCESS; hist_source hs; assert(hs.text_line_count() == 0); hs.add_value(1, bucket_type_t(1)); assert(hs.text_line_count() == 101); hs.add_value(2, bucket_type_t(1)); assert(hs.text_line_count() == 101); return retval; } lnav-0.7.0/test/test_json_format.sh000644 000765 000024 00000000503 12305016344 017615 0ustar00stackstaff000000 000000 #! /bin/bash lnav_test="${top_builddir}/src/lnav-test" run_test ${lnav_test} -n \ -I ${test_dir} \ ${test_dir}/logfile_json.json check_output "json log format is not working" < lb.dat < lb-2.dat grep -b '$' lb-2.dat | cut -f 1 -d : > lb.index line_count=`wc -l lb-2.dat` run_test ./drive_line_buffer -i lb.index -n 100 lb-2.dat check_output "Random reads don't match input?" < #include #include #include #include "auto_fd.hh" #include "line_buffer.hh" static void single_line(const char *data, int lendiff) { line_buffer lb; line_value lv; auto_fd pi[2]; off_t off = 0; bool ret; assert(auto_fd::pipe(pi) == 0); write(pi[1], data, strlen(data)); pi[1].reset(); lb.set_fd(pi[0]); ret = lb.read_line(off, lv); assert(ret); assert(off == strlen(data)); assert(lv.lv_len == strlen(data) - lendiff); ret = lb.read_line(off, lv); assert(!ret); } int main(int argc, char *argv[]) { int retval = EXIT_SUCCESS; single_line("Dexter Morgan", 0); single_line("Rudy Morgan\n", 1); return retval; } lnav-0.7.0/test/test_listview.sh000664 000765 000024 00000002112 12211635055 017144 0ustar00stackstaff000000 000000 #! /bin/bash run_test ./scripty -n -e ${srcdir}/listview_output.0 -- \ ./drive_listview < /dev/null on_error_fail_with "listview output does not match?" run_test ./scripty -n -e ${srcdir}/listview_output.1 -- \ ./drive_listview -t 1 < /dev/null on_error_fail_with "listview didn't move down?" run_test ./scripty -n -e ${srcdir}/listview_output.2 -- \ ./drive_listview -l 1 < /dev/null on_error_fail_with "Listview didn't move right?" run_test ./scripty -n -e ${srcdir}/listview_output.3 -- \ ./drive_listview -t 1 -l 1 < /dev/null on_error_fail_with "Listview didn't move left and right?" run_test ./scripty -n -e ${srcdir}/listview_output.4 -- \ ./drive_listview -y 1 -r 50 < /dev/null on_error_fail_with "Listview doesn't start down one line?" run_test ./scripty -n -e ${srcdir}/listview_output.5 -- \ ./drive_listview -y 1 -r 50 -h -1 < /dev/null on_error_fail_with "Listview isn't shorter?" run_test ./scripty -n -e ${srcdir}/listview_output.6 -- \ ./drive_listview -y 1 -r 50 -h -1 -t 1 < /dev/null on_error_fail_with "Listview didn't move down (2)?" lnav-0.7.0/test/test_log_accel.cc000644 000765 000024 00000004442 12311416221 017160 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include "log_accel.hh" static int64_t SIMPLE_TEST_POINTS[] = { 90, 80, 40, 30, 20, 10, -1 }; static log_accel::direction_t SIMPLE_TEST_DIRS[] = { log_accel::A_STEADY, log_accel::A_DECEL, log_accel::A_STEADY, log_accel::A_STEADY, log_accel::A_STEADY, log_accel::A_STEADY, log_accel::A_STEADY, }; int main(int argc, char *argv[]) { for (int point = 0; SIMPLE_TEST_POINTS[point] != -1; point++) { log_accel la; for (int lpc = point; SIMPLE_TEST_POINTS[lpc] != -1; lpc++) { if (!la.add_point(SIMPLE_TEST_POINTS[lpc])) { break; } } assert(SIMPLE_TEST_DIRS[point] == la.get_direction()); } return EXIT_SUCCESS; }lnav-0.7.0/test/test_logfile.sh000664 000765 000024 00000010603 12311037105 016714 0ustar00stackstaff000000 000000 #! /bin/bash run_test ./drive_logfile -f syslog_log ${srcdir}/logfile_syslog.0 on_error_fail_with "Didn't infer syslog log format?" run_test ./drive_logfile -f tcsh_history ${srcdir}/logfile_tcsh_history.0 on_error_fail_with "Didn't infer tcsh-history log format?" run_test ./drive_logfile -f access_log ${srcdir}/logfile_access_log.0 on_error_fail_with "Didn't infer access_log log format?" run_test ./drive_logfile -f strace_log ${srcdir}/logfile_strace_log.0 on_error_fail_with "Didn't infer strace_log log format?" run_test ./drive_logfile ${srcdir}/logfile_empty.0 on_error_fail_with "Didn't handle empty log?" touch -t 200711030923 ${srcdir}/logfile_syslog.0 run_test ./drive_logfile -t -f syslog_log ${srcdir}/logfile_syslog.0 check_output "Syslog timestamp interpreted incorrectly?" < logfile_syslog.1.gz run_test ./drive_logfile -t -f syslog_log logfile_syslog.1.gz check_output "Syslog timestamp incorrect for gzipped file?" < logfile_syslog.1.bz2 touch -t 200711030923 logfile_syslog.1.bz2 run_test ./drive_logfile -t -f syslog_log logfile_syslog.1.bz2 check_output "bzip2 file not loaded?" < #include #include #include #include "pcrepp.hh" int main(int argc, char *argv[]) { pcre_context_static<30> context; int retval = EXIT_SUCCESS; { pcrepp nomatch("nothing-to-match"); pcre_input pi("dummy"); assert(!nomatch.match(context, pi)); } { pcrepp match1("(\\w*)=(\\d+)"); pcre_input pi("a=1 b=2"); pcre_context::capture_t *cap; assert(match1.match(context, pi)); cap = context.all(); assert(cap->c_begin == 0); assert(cap->c_end == 3); assert((context.end() - context.begin()) == 2); assert(pi.get_substr(context.begin()) == "a"); assert(pi.get_substr(context.begin() + 1) == "1"); assert(pi.get_substr(context[1]) == "1"); assert(match1.match(context, pi)); assert((context.end() - context.begin()) == 2); assert(pi.get_substr(context.begin()) == "b"); assert(pi.get_substr(context.begin() + 1) == "2"); } { pcrepp match2(""); } { pcrepp match3("(?\\d+)(?\\w+)"); pcre_named_capture::iterator iter; const char *expected_names[] = { "var1", "var2", }; int index = 0; for (iter = match3.named_begin(); iter != match3.named_end(); ++iter, index++) { assert(strcmp(iter->pnc_name, expected_names[index]) == 0); } assert(match3.name_index("var2") == 1); pcre_input pi("123foo"); match3.match(context, pi); assert(pi.get_substr(context["var1"]) == "123"); } { pcre_context::capture cap(1, 4); pcre_input pi("\0foo", 0, 4); assert("foo" == pi.get_substr(&cap)); } return retval; } lnav-0.7.0/test/test_sessions.sh000644 000765 000024 00000003435 12312227465 017157 0ustar00stackstaff000000 000000 #! /bin/bash lnav_test="${top_builddir}/src/lnav-test" export HOME="./sessions" mkdir -p $HOME run_test ${lnav_test} -nq \ -c ";update access_log set log_mark = 1 where sc_bytes > 60000" \ -c ":goto 1" \ -c ":partition-name middle" \ -c ":save-session" \ ${test_dir}/logfile_access_log.0 check_output "setting log_mark is not working" <,/vmw/cgi/tramp,gPXE/0.9.7,-,HTTP/1.0,134,200 1,p.0,2009-07-20 22:59:29.000,3000,error,0,192.168.202.254,GET,-,,/vmw/vSphere/default/vmkboot.gz,gPXE/0.9.7,-,HTTP/1.0,46210,404 2,p.0,2009-07-20 22:59:29.000,0,info,0,192.168.202.254,GET,-,,/vmw/vSphere/default/vmkernel.gz,gPXE/0.9.7,-,HTTP/1.0,78929,200 EOF run_test ${lnav_test} -n \ -c ";select * from access_log where log_level >= 'warning'" \ -c ':write-csv-to -' \ ${test_dir}/logfile_access_log.0 check_output "loglevel collator is not working" <,/vmw/vSphere/default/vmkboot.gz,gPXE/0.9.7,-,HTTP/1.0,46210,404 EOF # XXX The timestamp on the file is used to determine the year for syslog files. touch -t 201311030923 ${test_dir}/logfile_syslog.0 run_test ${lnav_test} -n \ -c ";select * from syslog_log" \ -c ':write-csv-to -' \ ${test_dir}/logfile_syslog.0 check_output "syslog_log table is not working" <,sudo EOF run_test ${lnav_test} -n \ -c ";select * from syslog_log where log_time >= datetime('2013-11-03T09:47:02.000')" \ -c ':write-csv-to -' \ ${test_dir}/logfile_syslog.0 check_output "log_time collation is wrong" <,sudo EOF run_test ${lnav_test} -n \ -c ':filter-in sudo' \ -c ";select * from logline" \ -c ':write-csv-to -' \ ${test_dir}/logfile_syslog.0 check_output "logline table is not working" <,sudo,timstack,pts/6,/auto/wstimstack/rpms/lbuild/test,root,/usr/bin/tail /var/log/messages EOF run_test ${lnav_test} -n \ -c ";update access_log set log_mark = 1 where sc_bytes > 60000" \ -c ':write-to -' \ ${test_dir}/logfile_access_log.0 check_output "setting log_mark is not working" <,/vmw/cgi/tramp,gPXE/0.9.7,-,HTTP/1.0,134,200 1,middle,2009-07-20 22:59:29.000,3000,error,0,192.168.202.254,GET,-,,/vmw/vSphere/default/vmkboot.gz,gPXE/0.9.7,-,HTTP/1.0,46210,404 2,middle,2009-07-20 22:59:29.000,0,info,0,192.168.202.254,GET,-,,/vmw/vSphere/default/vmkernel.gz,gPXE/0.9.7,-,HTTP/1.0,78929,200 EOF run_test ${lnav_test} -n \ -c ":goto 1" \ -c ":partition-name middle" \ -c ":clear-partition" \ -c ";select * from access_log" \ -c ":write-csv-to -" \ ${test_dir}/logfile_access_log.0 check_output "clear-partition does not work" <,/vmw/cgi/tramp,gPXE/0.9.7,-,HTTP/1.0,134,200 1,p.0,2009-07-20 22:59:29.000,3000,error,0,192.168.202.254,GET,-,,/vmw/vSphere/default/vmkboot.gz,gPXE/0.9.7,-,HTTP/1.0,46210,404 2,p.0,2009-07-20 22:59:29.000,0,info,0,192.168.202.254,GET,-,,/vmw/vSphere/default/vmkernel.gz,gPXE/0.9.7,-,HTTP/1.0,78929,200 EOF run_test ${lnav_test} -n \ -c ":goto 1" \ -c ":partition-name middle" \ -c ":goto 2" \ -c ":clear-partition" \ -c ";select * from access_log" \ -c ":write-csv-to -" \ ${test_dir}/logfile_access_log.0 check_output "clear-partition does not work when in the middle of a part" <,/vmw/cgi/tramp,gPXE/0.9.7,-,HTTP/1.0,134,200 1,p.0,2009-07-20 22:59:29.000,3000,error,0,192.168.202.254,GET,-,,/vmw/vSphere/default/vmkboot.gz,gPXE/0.9.7,-,HTTP/1.0,46210,404 2,p.0,2009-07-20 22:59:29.000,0,info,0,192.168.202.254,GET,-,,/vmw/vSphere/default/vmkernel.gz,gPXE/0.9.7,-,HTTP/1.0,78929,200 EOF lnav-0.7.0/test/test_sql_coll_func.sh000664 000765 000024 00000004244 12302315201 020116 0ustar00stackstaff000000 000000 #! /bin/bash run_test ./drive_sql "select '192.168.1.10' < '192.168.1.2'" check_output "" < '' collate ipaddress" check_output "" < '' collate ipaddress: 1 EOF run_test ./drive_sql "select '192.168.1.2' < 'fe80::a85f:80b4:5cbe:8691' collate ipaddress" check_output "" < #include #include "top_status_source.hh" using namespace std; static time_t current_time = 1; time_t time(time_t *arg) { if (arg != NULL) *arg = current_time; return current_time; } int main(int argc, char *argv[]) { int retval = EXIT_SUCCESS; top_status_source tss; { status_field &sf = tss. statusview_value_for_field(top_status_source::TSF_TIME); attr_line_t val; tss.update_time(); val = sf.get_value(); assert(val.get_string() == sf.get_value().get_string()); current_time += 2; tss.update_time(); assert(val.get_string() != sf.get_value().get_string()); } return retval; } lnav-0.7.0/test/test_view_colors.sh000664 000765 000024 00000000231 12211635055 017631 0ustar00stackstaff000000 000000 #! /bin/bash run_test ./scripty -n -e ${srcdir}/view_colors_output.0 -- \ ./drive_view_colors < /dev/null on_error_fail_with "view colors are wrong?" lnav-0.7.0/test/test_vt52_curses.sh000664 000765 000024 00000000605 12211635055 017467 0ustar00stackstaff000000 000000 #! /bin/bash run_test ./scripty -n -r ${srcdir}/vt52_curses_input.0 \ -e ${srcdir}/vt52_curses_output.0 -- ./drive_vt52_curses < /dev/null on_error_fail_with "single line vt52 did not work?" run_test ./scripty -n -r ${srcdir}/vt52_curses_input.1 \ -e ${srcdir}/vt52_curses_output.1 -- ./drive_vt52_curses -y 5 < /dev/null on_error_fail_with "vt52 doesn't maintain past lines?" lnav-0.7.0/test/test_yajlpp.cc000664 000765 000024 00000004543 12211635055 016562 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file test_yajlpp.cc */ #include "config.h" #include #include #include "yajlpp.hh" const char *TEST_DATA = "[{ \"foo\": 0 }, { \"foo\": 1 }]"; static int FOO_COUNT = 0; static int read_foo(yajlpp_parse_context *ypc, long long value) { assert(value == FOO_COUNT); assert(ypc->ypc_array_index.back() == FOO_COUNT); FOO_COUNT += 1; return 1; } int main(int argc, char *argv[]) { struct json_path_handler test_handlers[] = { json_path_handler("#/foo", read_foo), json_path_handler() }; yajlpp_parse_context ypc("test_data", test_handlers); yajl_handle handle; handle = yajl_alloc(&ypc.ypc_callbacks, NULL, &ypc); yajl_parse(handle, (const unsigned char *)TEST_DATA, strlen(TEST_DATA)); yajl_complete_parse(handle); yajl_free(handle); assert(FOO_COUNT == 2); } lnav-0.7.0/test/view_colors_output.0000664 000765 000024 00000013564 12211635055 017754 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b6d1b5b6d1b5b33376d1b5b34306d1b5b313b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b323b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b333b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b343b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b353b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b363b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b373b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b383b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b393b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31303b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31313b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31323b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31333b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31343b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31353b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31363b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31373b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31383b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b31393b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32303b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32313b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32323b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32333b314820202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020201b5b32343b3148202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020200820081b5b3468201b5b346c1b5b481b5b33346d1b5b34306d54686973206973206c696e653a2030202020202020202020202020202020202020202020202020200d0a1b5b316d54686973206973206c696e653a2031202020202020202020202020202020202020202020202020200d0a1b5b6d1b5b33366d1b5b34306d54686973206973206c696e653a2032202020202020202020202020202020202020202020202020200d0a1b5b316d54686973206973206c696e653a2033202020202020202020202020202020202020202020202020200d0a1b5b6d1b5b33326d1b5b34306d54686973206973206c696e653a2034202020202020202020202020202020202020202020202020200d0a1b5b316d54686973206973206c696e653a2035202020202020202020202020202020202020202020202020200d0a1b5b6d1b5b33356d1b5b34306d54686973206973206c696e653a2036202020202020202020202020202020202020202020202020200d0a1b5b316d54686973206973206c696e653a2037202020202020202020202020202020202020202020202020200d0a1b5b6d1b5b33346d1b5b34306d54686973206973206c696e653a2038202020202020202020202020202020202020202020202020200d0a1b5b316d54686973206973206c696e653a2039202020202020202020202020202020202020202020202020200d0a1b5b6d1b5b33366d1b5b34306d54686973206973206c696e653a2031302020202020202020202020202020202020202020202020200d0a1b5b316d54686973206973206c696e653a2031312020202020202020202020202020202020202020202020200d0a1b5b6d1b5b33326d1b5b34306d54686973206973206c696e653a2031322020202020202020202020202020202020202020202020200d0a1b5b316d54686973206973206c696e653a2031332020202020202020202020202020202020202020202020200d0a1b5b6d1b5b33356d1b5b34306d54686973206973206c696e653a2031342020202020202020202020202020202020202020202020200d0a1b5b316d54686973206973206c696e653a2031352020202020202020202020202020202020202020202020201b5b31363b3137481b5b6d1b5b6d1b5b33376d1b5b34306d1b5b6d0d1b5b38421b5b4b1b5b32343b31481b5b324a1b5b3f34376c1b380d1b5b3f316c1b3e lnav-0.7.0/test/vt52_curses_input.0000664 000765 000024 00000000710 12211635055 017371 0ustar00stackstaff000000 000000 sleep 2.051763 write 31 sleep 0.311858 write 32 sleep 0.295852 write 33 sleep 0.319916 write 34 sleep 0.327742 write 35 sleep 0.328183 write 36 sleep 0.335896 write 37 sleep 0.360085 write 38 sleep 0.336000 write 39 sleep 0.376058 write 30 sleep 0.840149 write 61 sleep 0.783892 write 62 sleep 0.415990 write 63 sleep 0.280001 write 64 sleep 0.191901 write 65 sleep 0.295949 write 66 sleep 0.775841 write 67 sleep 0.399883 write 68 sleep 0.304016 write 69 lnav-0.7.0/test/vt52_curses_input.1000664 000765 000024 00000000710 12211635055 017372 0ustar00stackstaff000000 000000 sleep 1.124207 write 31 sleep 0.295830 write 32 sleep 0.487919 write 33 sleep 0.343913 write 34 sleep 0.303816 write 35 sleep 0.343703 write 36 sleep 0.295997 write 37 sleep 0.327862 write 38 sleep 0.295952 write 39 sleep 0.247670 write 30 sleep 0.911859 write 61 sleep 0.311780 write 62 sleep 0.407914 write 63 sleep 0.319836 write 64 sleep 0.199866 write 65 sleep 0.327904 write 66 sleep 0.359919 write 67 sleep 0.343907 write 68 sleep 0.288008 write 69 lnav-0.7.0/test/vt52_curses_output.0000664 000765 000024 00000000667 12211635055 017605 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a616263 # write 31 read 0d # write 32 read 1b5b4a # write 33 read 6465 # write 34 read 0d1b5b4a # write 35 read # write 36 read # write 37 read # write 38 read # write 39 read # write 30 read # write 61 read # write 62 read # write 63 read # write 64 read 616263 # write 65 read 0d1b5b4a # write 66 read 07 # write 67 read 6163646566 # write 68 read # write 69 lnav-0.7.0/test/vt52_curses_output.1000664 000765 000024 00000001313 12211635055 017573 0ustar00stackstaff000000 000000 read 1b29301b371b5b3f3437681b5b313b3234721b5b6d1b5b346c1b5b481b5b324a1b5b3542616263 # write 31 read 0d # write 32 read 1b5b4a # write 33 read 6465 # write 34 read 0d1b5b3138420a1b5b313841 # write 35 read 1b5b3138420a1b5b313941310a08 # write 36 read 1b5b3138420a1b5b313941320a08 # write 37 read 1b5b3138420a1b5b313941330a08 # write 38 read 1b5b3138420a1b5b313941340a08 # write 39 read 1b5b3138420a1b5b313941350a08 # write 30 read 1b5b3138420a1b5b313941360a08 # write 61 read 1b5b3138420a1b5b313941370a08 # write 62 read 1b5b3138420a1b5b313941380a08 # write 63 read 1b5b3138420a1b5b313941390a08 # write 64 read 616263 # write 65 read 0d1b5b4a # write 66 read 07 # write 67 read 6163646566 # write 68 read # write 69 lnav-0.7.0/test/log-samples/sample-27353a72ba4025448f261dcfa6ea16e474187795.txt000664 000765 000024 00000005302 12211635054 025315 0ustar00stackstaff000000 000000 Jun 3 07:00:23 Tim-Stacks-iMac.local sudo[2326]: stack : TTY=ttys002 ; PWD=/ ; USER=root ; COMMAND=/bin/ls key 53:53 ^ word 53:58 ^---^ stack val 53:58 ^---^ stack pair 53:58 ^---^ stack key 61:64 ^-^ TTY sym 65:72 ^-----^ ttys002 val 65:72 ^-----^ ttys002 pair 61:72 ^---------^ TTY=ttys002 key 75:78 ^-^ PWD path 79:80 ^ / val 79:80 ^ / pair 75:80 ^---^ PWD=/ key 83:87 ^--^ USER word 88:92 ^--^ root val 88:92 ^--^ root pair 83:92 ^-------^ USER=root key 95:102 ^-----^ COMMAND path 103:110 ^-----^ /bin/ls val 103:110 ^-----^ /bin/ls pair 95:110 ^-------------^ COMMAND=/bin/ls lnav-0.7.0/test/log-samples/sample-70c906b3c1a1cf03f15bde92ee78edfa6f9b7960.txt000664 000765 000024 00000007444 12211635055 026052 0ustar00stackstaff000000 000000 Jun 3 07:02:37 Tim-Stacks-iMac.local sudo[2717]: stack : TTY=ttys002 ; PWD=/ ; USER=root ; COMMAND=/usr/bin/env VAR1=foo ls key 53:53 ^ word 53:58 ^---^ stack val 53:58 ^---^ stack pair 53:58 ^---^ stack key 61:64 ^-^ TTY sym 65:72 ^-----^ ttys002 val 65:72 ^-----^ ttys002 pair 61:72 ^---------^ TTY=ttys002 key 75:78 ^-^ PWD path 79:80 ^ / val 79:80 ^ / pair 75:80 ^---^ PWD=/ key 83:87 ^--^ USER word 88:92 ^--^ root val 88:92 ^--^ root pair 83:92 ^-------^ USER=root key 95:102 ^-----^ COMMAND path 103:115 ^----------^ /usr/bin/env wspc 115:116 ^ sym 116:120 ^--^ VAR1 word 121:124 ^-^ foo wspc 124:125 ^ word 125:127 ^^ ls val 103:127 ^----------------------^ /usr/bin/env VAR1=foo ls pair 95:127 ^------------------------------^ COMMAND=/usr/bin/env VAR1=foo ls lnav-0.7.0/test/log-samples/sample-ad31f12d2adabd07e3ddda3ad5b0dbf6b49c4c99.txt000664 000765 000024 00000003660 12211635055 026372 0ustar00stackstaff000000 000000 Jun 2 00:34:32 Tim-Stacks-iMac kernel[0]: vmnet: VNetUserIf_Create: created userIf at 0xffffff802644f400. key 43:48 ^---^ vmnet quot 48:48 ^ val 48:48 ^ pair 43:48 ^---^ vmnet key 50:67 ^---------------^ VNetUserIf_Create word 69:76 ^-----^ created wspc 76:77 ^ sym 77:83 ^----^ userIf wspc 83:84 ^ word 84:86 ^^ at wspc 86:87 ^ hex 87:105 ^----------------^ 0xffffff802644f400 val 69:105 ^----------------------------------^ created userIf at 0xffffff802644f400 pair 50:105 ^-----------------------------------------------------^ VNetUserIf_Create: created userIf at 0xffffff802644f400 lnav-0.7.0/test/formats/jsontest/000775 000765 000024 00000000000 12315725123 017234 5ustar00stackstaff000000 000000 lnav-0.7.0/test/formats/jsontest/format.json000644 000765 000024 00000001066 12305015474 021420 0ustar00stackstaff000000 000000 { "test_log" : { "title" : "Test JSON Log", "json" : true, "file-pattern" : ".*\\.json.*", "description" : "Test config", "line-format" : [ { "field" : "ts" }, " ", { "field" : "lvl" }, " ", { "field" : "msg" } ], "level-field" : "lvl", "timestamp-field": "ts", "body-field" : "msg", "value" : { "user" : { "kind" : "string", "identifier" : true } } } } lnav-0.7.0/src/ansi_scrubber.cc000664 000765 000024 00000010640 12274102321 016642 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file ansi_scrubber.cc */ #include "config.h" #include #include "pcrepp.hh" #include "ansi_scrubber.hh" using namespace std; static pcrepp &ansi_regex(void) { static pcrepp retval("\x1b\\[([\\d=;]*)([a-zA-Z])"); return retval; } void scrub_ansi_string(std::string &str, string_attrs_t &sa) { view_colors &vc = view_colors::singleton(); pcre_context_static<60> context; pcrepp & regex = ansi_regex(); pcre_input pi(str); replace(str.begin(), str.end(), '\0', ' '); while (regex.match(context, pi)) { pcre_context::capture_t *caps = context.all(); struct line_range lr; bool has_attrs = false; int attrs = 0; int bg = 0; int fg = 0; int lpc; switch (pi.get_substr_start(&caps[2])[0]) { case 'm': for (lpc = caps[1].c_begin; lpc != (int)string::npos && lpc < caps[1].c_end; ) { int ansi_code = 0; if (sscanf(&(str[lpc]), "%d", &ansi_code) == 1) { if (90 <= ansi_code && ansi_code <= 97) { ansi_code -= 60; attrs |= A_STANDOUT; } if (30 <= ansi_code && ansi_code <= 37) { fg = ansi_code - 30; } if (40 <= ansi_code && ansi_code <= 47) { bg = ansi_code - 40; } switch (ansi_code) { case 1: attrs |= A_BOLD; break; case 2: attrs |= A_DIM; break; case 4: attrs |= A_UNDERLINE; break; case 7: attrs |= A_REVERSE; break; } } lpc = str.find(";", lpc); if (lpc != (int)string::npos) { lpc += 1; } } if (fg != 0 || bg != 0) { attrs |= vc.ansi_color_pair(fg, bg); } has_attrs = true; break; case 'C': { int spaces = 0; if (sscanf(&(str[caps[1].c_begin]), "%d", &spaces) == 1 && spaces > 0) { str.insert(caps[0].c_end, spaces, ' '); } } break; } str.erase(str.begin() + caps[0].c_begin, str.begin() + caps[0].c_end); if (has_attrs) { if (!sa.empty()) { sa.back().sa_range.lr_end = caps[0].c_begin; } lr.lr_start = caps[0].c_begin; lr.lr_end = -1; sa.push_back(string_attr(lr, &view_curses::VC_STYLE, attrs)); } pi.reset(str); } } lnav-0.7.0/src/ansi_scrubber.hh000664 000765 000024 00000004125 12304370522 016661 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file ansi_scrubber.hh */ #ifndef _ansi_scrubber_hh #define _ansi_scrubber_hh #include #include "view_curses.hh" #define ANSI_BOLD_START "\x1b[1m" #define ANSI_NORM "\x1b[0m" #define ANSI_BOLD(msg) ANSI_BOLD_START msg ANSI_NORM /** * Check a string for ANSI escape sequences, process them, remove them, and add * any style attributes to the given attribute container. * * @param str The string to check for ANSI escape sequences. * @param sa The container for any style attributes. */ void scrub_ansi_string(std::string &str, string_attrs_t &sa); #endif lnav-0.7.0/src/auto_fd.hh000664 000765 000024 00000016452 12306073006 015466 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file auto_fd.hh */ #ifndef __auto_fd_hh #define __auto_fd_hh #include #include #include #include #include #include "lnav_log.hh" /** * Resource management class for file descriptors. * * @see auto_ptr */ class auto_fd { public: /** * Wrapper for the posix pipe(2) function that stores the file descriptor * results in an auto_fd array. * * @param af An array of at least two auto_fd elements, where the first * contains the reader end of the pipe and the second contains the writer. * @return The result of the pipe(2) function. */ static int pipe(auto_fd *af) { int retval, fd[2]; require(fd != NULL); if ((retval = ::pipe(fd)) == 0) { af[0] = fd[0]; af[1] = fd[1]; } return retval; }; /** * Construct an auto_fd to manage the given file descriptor. * * @param fd The file descriptor to be managed. */ auto_fd(int fd = -1) : af_fd(fd) { require(fd >= -1); require(fd < (int)FD_SETSIZE); }; /** * Non-const copy constructor. Management of the file descriptor will be * transferred from the source to this object and the source will be * cleared. * * @param af The source of the file descriptor. */ auto_fd(auto_fd & af) : af_fd(af.release()) { }; /** * Const copy constructor. The file descriptor from the source will be * dup(2)'d and the new descriptor stored in this object. * * @param af The source of the file descriptor. */ auto_fd(const auto_fd &af) : af_fd(-1) { if (af.af_fd != -1 && (this->af_fd = dup(af.af_fd)) == -1) { throw std::bad_alloc(); } }; /** * Destructor that will close the file descriptor managed by this object. */ ~auto_fd() { this->reset(); }; /** @return The file descriptor as a plain integer. */ operator int(void) const { return this->af_fd; }; /** * Replace the current descriptor with the given one. The current * descriptor will be closed. * * @param fd The file descriptor to store in this object. * @return *this */ auto_fd &operator =(int fd) { require(fd >= -1); require(fd < (int)FD_SETSIZE); this->reset(fd); return *this; }; /** * Transfer management of the given file descriptor to this object. * * @param af The old manager of the file descriptor. * @return *this */ auto_fd &operator =(auto_fd & af) { this->reset(af.release()); return *this; }; /** * Return a pointer that can be passed to functions that require an out * parameter for file descriptors (e.g. openpty). * * @return A pointer to the internal integer. */ int *out(void) { this->reset(); return &this->af_fd; }; /** * Stop managing the file descriptor in this object and return its value. * * @return The file descriptor. */ int release(void) { int retval = this->af_fd; this->af_fd = -1; return retval; }; /** * @return The file descriptor. */ int get(void) const { return this->af_fd; }; /** * Closes the current file descriptor and replaces its value with the given * one. * * @param fd The new file descriptor to be managed. */ void reset(int fd = -1) { require(fd >= -1); require(fd < (int)FD_SETSIZE); if (this->af_fd != fd) { if (this->af_fd != -1) { close(this->af_fd); } this->af_fd = fd; } }; private: int af_fd; /*< The managed file descriptor. */ }; class auto_pipe { public: static const int STDIO_FD_COUNT = 3; auto_pipe(int child_fd = -1, int child_flags = O_RDONLY) : ap_child_flags(child_flags), ap_child_fd(child_fd) { switch (child_fd) { case STDIN_FILENO: this->ap_child_flags = O_RDONLY; break; case STDOUT_FILENO: case STDERR_FILENO: this->ap_child_flags = O_WRONLY; break; } }; int open() { return auto_fd::pipe(this->ap_fd); }; void close() { this->ap_fd[0].reset(); this->ap_fd[1].reset(); }; auto_fd &read_end() { return this->ap_fd[0]; }; auto_fd &write_end() { return this->ap_fd[1]; }; void after_fork(pid_t child_pid) { int new_fd = -1; switch (child_pid) { case -1: this->close(); break; case 0: if (this->ap_child_flags == O_RDONLY) { this->write_end().reset(); if (this->read_end() == -1) { this->read_end() = ::open("/dev/null", O_RDONLY); } new_fd = this->read_end(); } else { this->read_end().reset(); if (this->write_end() == -1) { this->write_end() = ::open("/dev/null", O_WRONLY); } new_fd = this->write_end(); } if (this->ap_child_fd != -1) { if (new_fd != this->ap_child_fd) { dup2(new_fd, this->ap_child_fd); this->close(); } } break; default: if (this->ap_child_flags == O_RDONLY) { this->read_end().reset(); } else { this->write_end().reset(); } break; } }; int ap_child_flags; int ap_child_fd; auto_fd ap_fd[2]; }; #endif lnav-0.7.0/src/auto_mem.hh000664 000765 000024 00000007271 12306074423 015656 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file auto_mem.hh */ #ifndef __auto_mem_hh #define __auto_mem_hh #include #include #include #include typedef void (*free_func_t)(void *); /** * Resource management class for memory allocated by a custom allocator. * * @param T The object type. * @param auto_free The function to call to free the managed object. */ template class auto_mem { public: auto_mem(T *ptr = NULL) : am_ptr(ptr), am_free_func(default_free) { }; auto_mem(auto_mem & am) : am_ptr(am.release()), am_free_func(am.am_free_func) {}; template auto_mem(F free_func) : am_ptr(NULL), am_free_func((void(*) (void *))free_func) { }; ~auto_mem() { this->reset(); }; operator T *(void) const { return this->am_ptr; }; auto_mem &operator =(T *ptr) { this->reset(ptr); return *this; }; auto_mem &operator =(auto_mem & am) { this->reset(am.release()); this->am_free_func = am.am_free_func; return *this; }; T *release(void) { T *retval = this->am_ptr; this->am_ptr = NULL; return retval; }; T *in(void) const { return this->am_ptr; }; T **out(void) { this->reset(); return &this->am_ptr; }; void reset(T *ptr = NULL) { if (this->am_ptr != ptr) { if (this->am_ptr != NULL) { this->am_free_func(this->am_ptr); } this->am_ptr = ptr; } }; private: T * am_ptr; void (*am_free_func)(void *); }; template class static_root_mem { public: static_root_mem() { memset(&this->srm_value, 0, sizeof(T)); }; ~static_root_mem() { free_func(&this->srm_value); }; const T *operator->(void) const { return &this->srm_value; }; const T &in(void) const { return this->srm_value; }; T *inout(void) { return &this->srm_value; }; private: static_root_mem &operator =(T &) { return *this; }; static_root_mem &operator =(static_root_mem &) { return *this; }; T srm_value; }; #endif lnav-0.7.0/src/auto_pid.hh000664 000765 000024 00000006011 12216211402 015631 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file auto_pid.hh */ #ifndef __auto_pid_hh #define __auto_pid_hh #include #include #include #include class auto_pid { public: auto_pid(pid_t child = -1) : ap_child(child), ap_status(0) {}; auto_pid(auto_pid &other) : ap_child(other.release()), ap_status(0) { }; ~auto_pid() { this->reset(); }; auto_pid &operator =(auto_pid &other) { this->reset(other.release()); this->ap_status = other.ap_status; return *this; }; pid_t release() { pid_t retval = this->ap_child; this->ap_child = -1; return retval; }; int status() const { return this->ap_status; }; bool wait_for_child(int options = 0) { if (this->ap_child != -1) { int rc; while ((rc = waitpid(this->ap_child, &this->ap_status, options)) < 0 && (errno == EINTR)) { ; } if (rc > 0) { this->ap_child = -1; } } return this->ap_child == -1; }; void reset(pid_t child = -1) { if (this->ap_child != child) { this->ap_status = 0; if (this->ap_child != -1) { kill(this->ap_child, SIGTERM); this->wait_for_child(); } this->ap_child = child; } }; private: auto_pid(const auto_pid &other) { }; pid_t ap_child; int ap_status; }; #endif lnav-0.7.0/src/bin2c.c000664 000765 000024 00000004354 12211635053 014664 0ustar00stackstaff000000 000000 // bin2c.c // // convert a binary file into a C source vector // // THE "BEER-WARE LICENSE" (Revision 3.1415): // sandro AT sigala DOT it wrote this file. As long as you retain this notice you can do // whatever you want with this stuff. If we meet some day, and you think this stuff is // worth it, you can buy me a beer in return. Sandro Sigala // // syntax: bin2c [-c] [-z] // // -c add the "const" keyword to definition // -z terminate the array with a zero (useful for embedded C strings) // // examples: // bin2c -c myimage.png myimage_png.cpp // bin2c -z sometext.txt sometext_txt.cpp #include #include #include #include #ifndef PATH_MAX #define PATH_MAX 1024 #endif int useconst = 0; int zeroterminated = 0; int myfgetc(FILE *f) { int c = fgetc(f); if (c == EOF && zeroterminated) { zeroterminated = 0; return 0; } return c; } void process(const char *ifname, const char *ofname) { FILE *ifile, *ofile; ifile = fopen(ifname, "rb"); if (ifile == NULL) { fprintf(stderr, "cannot open %s for reading\n", ifname); exit(1); } ofile = fopen(ofname, "wb"); if (ofile == NULL) { fprintf(stderr, "cannot open %s for writing\n", ofname); exit(1); } char buf[PATH_MAX], *p; const char *cp; if ((cp = strrchr(ifname, '/')) != NULL) { ++cp; } else { if ((cp = strrchr(ifname, '\\')) != NULL) ++cp; else cp = ifname; } strcpy(buf, cp); for (p = buf; *p != '\0'; ++p) { if (!isalnum(*p)) *p = '_'; } fprintf(ofile, "%sunsigned char %s[] = {\n", useconst ? "const " : "", buf); int c, col = 1; while ((c = myfgetc(ifile)) != EOF) { if (col >= 78 - 6) { fputc('\n', ofile); col = 1; } fprintf(ofile, "0x%.2x, ", c); col += 6; } fprintf(ofile, "\n};\n"); fclose(ifile); fclose(ofile); } void usage(void) { fprintf(stderr, "usage: bin2c [-cz] \n"); exit(1); } int main(int argc, char **argv) { while (argc > 3) { if (!strcmp(argv[1], "-c")) { useconst = 1; --argc; ++argv; } else if (!strcmp(argv[1], "-z")) { zeroterminated = 1; --argc; ++argv; } else { usage(); } } if (argc != 3) { usage(); } process(argv[1], argv[2]); return 0; } lnav-0.7.0/src/bookmarks.cc000664 000765 000024 00000004534 12306073073 016025 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file bookmarks.cc */ #include "config.h" #include "bookmarks.hh" template LineType bookmark_vector::next(LineType start) { typename bookmark_vector::iterator ub; LineType retval(-1); require(start >= -1); ub = upper_bound(this->begin(), this->end(), start); if (ub != this->end()) { retval = *ub; } ensure(retval == -1 || start < retval); return retval; } template LineType bookmark_vector::prev(LineType start) { typename bookmark_vector::iterator lb; LineType retval(-1); require(start >= 0); lb = lower_bound(this->begin(), this->end(), start); if (lb != this->begin()) { lb -= 1; retval = *lb; } ensure(retval < start); return retval; } template class bookmark_vector; lnav-0.7.0/src/bookmarks.hh000664 000765 000024 00000007744 12306073120 016036 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file bookmarks.hh */ #ifndef __bookmarks_hh #define __bookmarks_hh #include #include #include #include #include "lnav_log.hh" #include "listview_curses.hh" struct bookmark_metadata { std::string bm_name; }; /** * Extension of the STL vector that is used to store bookmarks for * files being viewed, where a bookmark is just a particular line in * the file(s). The value-added over the standard vector are some * methods for doing content-wise iteration. In other words, given a * value that may or may not be in the vector, find the next or * previous value that is in the vector. * * @param LineType The type used to store line numbers. (e.g. * vis_line_t or content_line_t) * * @note The vector is expected to be sorted. */ template class bookmark_vector : public std::vector { public: /** * Insert a bookmark into this vector, but only if it is not already in the * vector. * * @param vl The line to bookmark. */ typename bookmark_vector::iterator insert_once(LineType vl) { typename bookmark_vector::iterator lb, retval; require(vl >= 0); lb = std::lower_bound(this->begin(), this->end(), vl); if (lb == this->end() || *lb != vl) { this->insert(lb, vl); retval = this->end(); } else { retval = lb; } return retval; }; /** * @param start The value to start the search for the next bookmark. * @return The next bookmark value in the vector or -1 if there are * no more remaining bookmarks. If the 'start' value is a bookmark, * the next bookmark is returned. If the 'start' value is not a * bookmark, the next highest value in the vector is returned. */ LineType next(LineType start); /** * @param start The value to start the search for the previous * bookmark. * @return The previous bookmark value in the vector or -1 if there * are no more prior bookmarks. * @see next */ LineType prev(LineType start); }; /** * Dummy type whose instances are used to distinguish between * bookmarks maintained by different source modules. */ class bookmark_type_t { }; /** * Map of bookmark types to bookmark vectors. */ template struct bookmarks { typedef std::map > type; }; typedef bookmarks::type vis_bookmarks; #endif lnav-0.7.0/src/bottom_status_source.hh000664 000765 000024 00000017106 12305366724 020344 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _bottom_status_source_hh #define _bottom_status_source_hh #include #include "grep_proc.hh" #include "textview_curses.hh" #include "logfile_sub_source.hh" #include "status_controllers.hh" class bottom_status_source : public status_data_source, public grep_proc_control { public: typedef listview_curses::action::mem_functor_t< bottom_status_source> lv_functor_t; typedef enum { BSF_LINE_NUMBER, BSF_PERCENT, BSF_HITS, BSF_FILTERED, BSF_LOADING, BSF_HELP, BSF__MAX } field_t; bottom_status_source() : line_number_wire(*this, &bottom_status_source::update_line_number), percent_wire(*this, &bottom_status_source::update_percent), marks_wire(*this, &bottom_status_source::update_marks), bss_prompt(80, view_colors::VCR_STATUS), bss_error(80, view_colors::VCR_ALERT_STATUS), bss_hit_spinner(0), bss_load_percent(0) { this->bss_fields[BSF_LINE_NUMBER].set_width(10); this->bss_fields[BSF_PERCENT].set_width(4); this->bss_fields[BSF_HITS].set_width(36); this->bss_fields[BSF_FILTERED].set_width(20); this->bss_fields[BSF_FILTERED].set_role(view_colors::VCR_BOLD_STATUS); this->bss_fields[BSF_LOADING].set_width(13); this->bss_fields[BSF_LOADING].set_cylon(true); this->bss_fields[BSF_LOADING].right_justify(true); this->bss_fields[BSF_HELP].set_width(14); this->bss_fields[BSF_HELP].set_value("?:View Help"); this->bss_fields[BSF_HELP].right_justify(true); }; virtual ~bottom_status_source() { }; lv_functor_t line_number_wire; lv_functor_t percent_wire; lv_functor_t marks_wire; status_field &get_field(field_t id) { return this->bss_fields[id]; }; void set_prompt(const std::string &prompt) { this->bss_prompt.set_value(prompt); }; void grep_error(std::string msg) { this->bss_error.set_value(msg); }; size_t statusview_fields(void) { size_t retval; if (this->bss_prompt.empty() && this->bss_error.empty()) { retval = BSF__MAX; } else{ retval = 1; } return retval; }; status_field &statusview_value_for_field(int field) { if (!this->bss_error.empty()) { return this->bss_error; } else if (!this->bss_prompt.empty()) { return this->bss_prompt; } else { return this->get_field((field_t)field); } }; void update_line_number(listview_curses *lc) { status_field &sf = this->bss_fields[BSF_LINE_NUMBER]; if (lc->get_inner_height() == 0) { sf.set_value("L0"); } else { sf.set_value("L%'d", (int)lc->get_top()); } }; void update_percent(listview_curses *lc) { status_field &sf = this->bss_fields[BSF_PERCENT]; vis_line_t top = lc->get_top(); vis_line_t bottom, height; unsigned long width; double percent; lc->get_dimensions(height, width); if (lc->get_inner_height() > 0) { bottom = std::min(top + height - vis_line_t(1), vis_line_t(lc->get_inner_height() - 1)); percent = (double)(bottom + 1); percent /= (double)lc->get_inner_height(); percent *= 100.0; } else { percent = 0.0; } sf.set_value("%3d%%", (int)percent); }; void update_marks(listview_curses *lc) { textview_curses *tc = static_cast(lc); vis_bookmarks &bm = tc->get_bookmarks(); status_field &sf = this->bss_fields[BSF_HITS]; if (bm.find(&textview_curses::BM_SEARCH) != bm.end()) { bookmark_vector &bv = bm[&textview_curses::BM_SEARCH]; bookmark_vector::iterator lb; lb = std::lower_bound(bv.begin(), bv.end(), tc->get_top()); if (lb != bv.end() && *lb == tc->get_top()) { sf.set_value(" Hit %'d of %'d", std::distance(bv.begin(), lb) + 1, tc->get_match_count()); } else { sf.set_value("%'9d hits", tc->get_match_count()); } } else { sf.clear(); } }; void update_hits(textview_curses *tc) { status_field & sf = this->bss_fields[BSF_HITS]; view_colors::role_t new_role; if (tc->is_searching()) { this->bss_hit_spinner += 1; if (this->bss_hit_spinner % 2) { new_role = view_colors::VCR_ACTIVE_STATUS; } else{ new_role = view_colors::VCR_ACTIVE_STATUS2; } sf.set_cylon(true); } else { new_role = view_colors::VCR_STATUS; sf.set_cylon(false); } // this->bss_error.clear(); sf.set_role(new_role); this->update_marks(tc); }; void update_loading(off_t off, size_t total) { status_field &sf = this->bss_fields[BSF_LOADING]; if ((size_t)off == total) { sf.set_role(view_colors::VCR_STATUS); sf.clear(); } else { int pct = (int)(((double)off / (double)total) * 100.0); if (this->bss_load_percent != pct) { this->bss_load_percent = pct; sf.set_role(view_colors::VCR_ACTIVE_STATUS2); sf.set_value(" Loading %2d%% ", pct); } } }; void update_filtered(logfile_sub_source &lss) { status_field &sf = this->bss_fields[BSF_FILTERED]; if (lss.get_filtered_count() == 0) { sf.clear(); } else{ sf.set_value("%'9d Not Shown", lss.get_filtered_count()); } }; private: status_field bss_prompt; status_field bss_error; status_field bss_fields[BSF__MAX]; int bss_hit_spinner; int bss_load_percent; }; #endif lnav-0.7.0/src/byte_array.hh000664 000765 000024 00000005615 12306074204 016206 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __byte_array_hh #define __byte_array_hh #include #include #include #include #include "lnav_log.hh" template struct byte_array { static const size_t BYTE_COUNT = COUNT * sizeof(T); byte_array() { }; byte_array(const byte_array &other) { memcpy(this->ba_data, other.ba_data, BYTE_COUNT); }; bool operator<(const byte_array &other) const { return memcmp(this->ba_data, other.ba_data, BYTE_COUNT) < 0; }; bool operator!=(const byte_array &other) const { return memcmp(this->ba_data, other.ba_data, BYTE_COUNT) != 0; }; void clear(void) { memset(this->ba_data, 0, BYTE_COUNT); }; void to_string(char *buffer) const { require(buffer != NULL); for (size_t lpc = 0; lpc < BYTE_COUNT; lpc++) { snprintf(&buffer[lpc * 2], 3, "%02x", this->ba_data[lpc]); } }; std::string to_string() const { char buffer[BYTE_COUNT * 2 + 1]; this->to_string(buffer); return std::string(buffer); } const unsigned char *in() const { return this->ba_data; }; T *out(int offset = 0) { T *ptr = (T *)this->ba_data; return &ptr[offset]; }; unsigned char ba_data[BYTE_COUNT]; }; #endif lnav-0.7.0/src/collation-functions.cc000664 000765 000024 00000011654 12302315024 020017 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file logfile_sub_source.hh */ #include "config.h" #include #include #include #include #include #include #include #include "log_format.hh" extern "C" { #include "strnatcmp.h" } #define MAX_ADDR_LEN 128 static int try_inet_pton(int p_len, const char *p, char *n) { static int family[] = { AF_INET6, AF_INET, AF_MAX }; char buf[MAX_ADDR_LEN]; int retval = AF_MAX; strncpy(buf, p, p_len); buf[p_len] = '\0'; for (int lpc = 0; family[lpc] != AF_MAX; lpc++) { if (inet_pton(family[lpc], buf, n) == 1) { retval = family[lpc]; break; } } return retval; } static int convert_v6_to_v4(int family, char *n) { struct in6_addr *ia = (struct in6_addr *)n; if (family == AF_INET6 && (IN6_IS_ADDR_V4COMPAT(ia) || IN6_IS_ADDR_V4MAPPED(ia))) { family = AF_INET; memmove(n, n + 12, sizeof(struct in_addr)); } return family; } static int ipaddress(void *ptr, int a_len, const void *a_in, int b_len, const void *b_in) { char a_addr[sizeof(struct in6_addr)], b_addr[sizeof(struct in6_addr)]; const char *a_str = (const char *)a_in, *b_str = (const char *)b_in; int a_family, b_family, retval; if (a_len > MAX_ADDR_LEN || b_len > MAX_ADDR_LEN) { return strnatcasecmp(a_len, a_str, b_len, b_str); } a_family = try_inet_pton(a_len, a_str, a_addr); b_family = try_inet_pton(b_len, b_str, b_addr); if (a_family == AF_MAX && b_family == AF_MAX) { return strnatcasecmp(a_len, a_str, b_len, b_str); } else if (a_family == AF_MAX && b_family != AF_MAX) { retval = -1; } else if (a_family != AF_MAX && b_family == AF_MAX) { retval = 1; } else { a_family = convert_v6_to_v4(a_family, a_addr); b_family = convert_v6_to_v4(b_family, b_addr); if (a_family == b_family) { retval = memcmp(a_addr, b_addr, a_family == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr)); } else if (a_family == AF_INET) { retval = -1; } else { retval = 1; } } return retval; } static int sql_strnatcmp(void *ptr, int a_len, const void *a_in, int b_len, const void *b_in) { return strnatcmp(a_len, (char *)a_in, b_len, (char *)b_in); } static int sql_strnatcasecmp(void *ptr, int a_len, const void *a_in, int b_len, const void *b_in) { return strnatcasecmp(a_len, (char *)a_in, b_len, (char *)b_in); } static int sql_loglevelcmp(void *ptr, int a_len, const void *a_in, int b_len, const void *b_in) { return logline::levelcmp((const char *)a_in, a_len, (const char *)b_in, b_len); } int register_collation_functions(sqlite3 *db) { sqlite3_create_collation(db, "ipaddress", SQLITE_UTF8, NULL, ipaddress); sqlite3_create_collation(db, "naturalcase", SQLITE_UTF8, NULL, sql_strnatcmp); sqlite3_create_collation(db, "naturalnocase", SQLITE_UTF8, NULL, sql_strnatcasecmp); sqlite3_create_collation(db, "loglevel", SQLITE_UTF8, NULL, sql_loglevelcmp); return 0; } lnav-0.7.0/src/column_namer.hh000664 000765 000024 00000005626 12272210572 016530 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file column_namer.hh */ #ifndef _column_namer_hh #define _column_namer_hh #include #include #include #include class column_namer { public: column_namer() { this->cn_builtin_names.push_back("col"); }; bool existing_name(const std::string &in_name) const { if (find(this->cn_builtin_names.begin(), this->cn_builtin_names.end(), in_name) != this->cn_builtin_names.end()) { return true; } else if (find(this->cn_names.begin(), this->cn_names.end(), in_name) != this->cn_names.end()) { return true; } return false; }; std::string add_column(const std::string &in_name) { std::string base_name = in_name, retval; size_t buf_size; int num = 0; buf_size = in_name.length() + 64; char buffer[buf_size]; if (in_name == "") { base_name = "col"; } retval = base_name; while (this->existing_name(retval)) { snprintf(buffer, buf_size, "%s_%d", base_name.c_str(), num); retval = buffer; num += 1; } this->cn_names.push_back(retval); return retval; }; std::vector cn_builtin_names; std::vector cn_names; }; #endif lnav-0.7.0/src/config.h.in000664 000765 000024 00000010341 12313323151 015533 0ustar00stackstaff000000 000000 /* src/config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_BZLIB_H /* Define to 1 if a SysV or X/Open compatible Curses library is present */ #undef HAVE_CURSES /* Define to 1 if library supports color (enhanced functions) */ #undef HAVE_CURSES_COLOR /* Define to 1 if library supports X/Open Enhanced functions */ #undef HAVE_CURSES_ENHANCED /* Define to 1 if is present */ #undef HAVE_CURSES_H /* Define to 1 if library supports certain obsolete features */ #undef HAVE_CURSES_OBSOLETE /* Define to 1 if you have the declaration of `tzname', and to 0 if you don't. */ #undef HAVE_DECL_TZNAME /* Define to 1 if you have the header file. */ #undef HAVE_EXECINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `pcre' library (-lpcre). */ #undef HAVE_LIBPCRE /* Define to 1 if you have the `pcrecpp' library (-lpcrecpp). */ #undef HAVE_LIBPCRECPP /* Define to 1 if you have the `readline' library (-lreadline). */ #undef HAVE_LIBREADLINE /* Define to 1 if you have the header file. */ #undef HAVE_LIBUTIL_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if the Ncurses library is present */ #undef HAVE_NCURSES /* Define to 1 if the NcursesW library is present */ #undef HAVE_NCURSESW /* Define to 1 if is present */ #undef HAVE_NCURSESW_CURSES_H /* Define to 1 if is present */ #undef HAVE_NCURSESW_H /* Define to 1 if is present */ #undef HAVE_NCURSES_CURSES_H /* Define to 1 if is present */ #undef HAVE_NCURSES_H /* Define to 1 if you have the header file. */ #undef HAVE_PCRE_H /* Define to 1 if you have the header file. */ #undef HAVE_PCRE_PCRE_H /* Define to 1 if you have the header file. */ #undef HAVE_PTY_H /* 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_READLINE_H /* sqlite3 */ #undef HAVE_SQLITE3 /* Have the sqlite3_stmt_readonly function */ #undef HAVE_SQLITE3_STMT_READONLY /* 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 header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if `tm_zone' is a member of `struct tm'. */ #undef HAVE_STRUCT_TM_TM_ZONE /* 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_TTYDEFAULTS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use `HAVE_STRUCT_TM_TM_ZONE' instead. */ #undef HAVE_TM_ZONE /* Define to 1 if you don't have `tm_zone' but do have the external array `tzname'. */ #undef HAVE_TZNAME /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_UTIL_H /* Define to 1 if you have the header file. */ #undef HAVE_ZLIB_H /* 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 /* The size of `off_t', as computed by sizeof. */ #undef SIZEOF_OFF_T /* The size of `size_t', as computed by sizeof. */ #undef SIZEOF_SIZE_T /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* Version number of package */ #undef VERSION /* Need pread */ #undef _BSD_SOURCE lnav-0.7.0/src/data_parser.cc000664 000765 000024 00000012046 12211635053 016314 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "data_parser.hh" using namespace std; data_format data_parser::FORMAT_SEMI("semi", DT_COMMA, DT_SEMI); data_format data_parser::FORMAT_COMMA("comma", DT_INVALID, DT_COMMA); data_format data_parser::FORMAT_PLAIN("plain", DT_INVALID, DT_INVALID); FILE *data_parser::TRACE_FILE; data_format_state_t dfs_prefix_next(data_format_state_t state, data_token_t next_token) { data_format_state_t retval = state; switch (state) { case DFS_INIT: switch (next_token) { case DT_PATH: case DT_COLON: case DT_EQUALS: case DT_CONSTANT: case DT_EMAIL: case DT_WORD: case DT_SYMBOL: case DT_OCTAL_NUMBER: case DT_HEX_NUMBER: case DT_NUMBER: case DT_WHITE: case DT_LSQUARE: case DT_RSQUARE: case DT_LANGLE: case DT_RANGLE: break; default: retval = DFS_ERROR; break; } break; case DFS_EXPECTING_SEP: case DFS_ERROR: retval = DFS_ERROR; break; default: break; } return retval; } data_format_state_t dfs_semi_next(data_format_state_t state, data_token_t next_token) { data_format_state_t retval = state; switch (state) { case DFS_INIT: switch (next_token) { case DT_COMMA: case DT_SEMI: retval = DFS_ERROR; break; default: retval = DFS_KEY; break; } break; case DFS_KEY: switch (next_token) { case DT_COLON: case DT_EQUALS: retval = DFS_VALUE; break; case DT_SEMI: retval = DFS_ERROR; break; default: break; } break; case DFS_VALUE: switch (next_token) { case DT_SEMI: retval = DFS_INIT; break; default: break; } break; case DFS_EXPECTING_SEP: case DFS_ERROR: retval = DFS_ERROR; break; } return retval; } data_format_state_t dfs_comma_next(data_format_state_t state, data_token_t next_token) { data_format_state_t retval = state; switch (state) { case DFS_INIT: switch (next_token) { case DT_COMMA: break; case DT_SEMI: retval = DFS_ERROR; break; default: retval = DFS_KEY; break; } break; case DFS_KEY: switch (next_token) { case DT_COLON: case DT_EQUALS: retval = DFS_VALUE; break; case DT_COMMA: retval = DFS_INIT; break; case DT_WORD: retval = DFS_EXPECTING_SEP; break; case DT_SEMI: retval = DFS_ERROR; break; default: break; } break; case DFS_EXPECTING_SEP: switch (next_token) { case DT_COLON: case DT_EQUALS: retval = DFS_VALUE; break; case DT_COMMA: case DT_SEMI: retval = DFS_ERROR; break; default: break; } break; case DFS_VALUE: switch (next_token) { case DT_COMMA: retval = DFS_INIT; break; case DT_COLON: case DT_EQUALS: retval = DFS_ERROR; break; default: break; } break; case DFS_ERROR: retval = DFS_ERROR; break; } return retval; } lnav-0.7.0/src/data_parser.hh000664 000765 000024 00000074623 12310230131 016323 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __data_parser_hh #define __data_parser_hh #include #include "spookyhash/SpookyV2.h" #include #include #include #include #include "lnav_log.hh" #include "yajlpp.hh" #include "pcrepp.hh" #include "byte_array.hh" #include "data_scanner.hh" #define ELEMENT_LIST_T(var) var("" #var, __FILE__, __LINE__) #define PUSH_FRONT(elem) push_front(elem, __FILE__, __LINE__) #define PUSH_BACK(elem) push_back(elem, __FILE__, __LINE__) #define POP_FRONT(elem) pop_front(__FILE__, __LINE__) #define POP_BACK(elem) pop_back(__FILE__, __LINE__) #define SPLICE(pos, other, first, last) splice(pos, other, first, last, \ __FILE__, __LINE__) template void strip(Container &container, UnaryPredicate p) { while (!container.empty() && p(container.front())) { container.POP_FRONT(); } while (!container.empty() && p(container.back())) { container.POP_BACK(); } } enum data_format_state_t { DFS_ERROR = -1, DFS_INIT, DFS_KEY, DFS_EXPECTING_SEP, DFS_VALUE, }; struct data_format { data_format(const char *name, data_token_t appender = DT_INVALID, data_token_t terminator = DT_INVALID) : df_name(name), df_appender(appender), df_terminator(terminator) {}; const char * df_name; const data_token_t df_appender; const data_token_t df_terminator; }; data_format_state_t dfs_prefix_next(data_format_state_t state, data_token_t next_token); data_format_state_t dfs_semi_next(data_format_state_t state, data_token_t next_token); data_format_state_t dfs_comma_next(data_format_state_t state, data_token_t next_token); #define LIST_INIT_TRACE \ do { \ if (TRACE_FILE != NULL) { \ fprintf(TRACE_FILE, \ "%p %s:%d %s %s\n", \ this, \ fn, line, \ __func__, \ varname); \ } \ } while (false) #define LIST_DEINIT_TRACE \ do { \ if (TRACE_FILE != NULL) { \ fprintf(TRACE_FILE, \ "%p %s:%d %s\n", \ this, \ fn, line, \ __func__); \ } \ } while (false) #define ELEMENT_TRACE \ do { \ if (TRACE_FILE != NULL) { \ fprintf(TRACE_FILE, \ "%p %s:%d %s %s %d:%d\n", \ this, \ fn, line, \ __func__, \ data_scanner::token2name(elem.e_token), \ elem.e_capture.c_begin, \ elem.e_capture.c_end); \ } \ } while (false) #define LIST_TRACE \ do { \ if (TRACE_FILE != NULL) { \ fprintf(TRACE_FILE, \ "%p %s:%d %s\n", \ this, \ fn, line, \ __func__); \ } \ } while (false) #define SPLICE_TRACE \ do { \ if (TRACE_FILE != NULL) { \ fprintf(TRACE_FILE, \ "%p %s:%d %s %d %p %d:%d\n", \ this, \ fn, line, \ __func__, \ (int)std::distance(this->begin(), pos), \ &other, \ (int)std::distance(other.begin(), first), \ (int)std::distance(last, other.end())); \ } \ } while (false); #define POINT_TRACE(name) \ do { \ if (TRACE_FILE) { \ fprintf(TRACE_FILE, \ "0x0 %s:%d point %s\n", \ __FILE__, __LINE__, \ name); \ } \ } while (false); class data_parser { public: static data_format FORMAT_SEMI; static data_format FORMAT_COMMA; static data_format FORMAT_PLAIN; static FILE *TRACE_FILE; typedef byte_array<2, uint64> schema_id_t; struct element; /* typedef std::list element_list_t; */ class element_list_t : public std::list { public: element_list_t(const char *varname, const char *fn, int line) { LIST_INIT_TRACE; } element_list_t() { const char *varname = "_anon2_"; const char *fn = __FILE__; int line = __LINE__; LIST_INIT_TRACE; }; ~element_list_t() { const char *fn = __FILE__; int line = __LINE__; LIST_DEINIT_TRACE; }; void push_front(const element &elem, const char *fn, int line) { ELEMENT_TRACE; this->std::list::push_front(elem); }; void push_back(const element &elem, const char *fn, int line) { ELEMENT_TRACE; this->std::list::push_back(elem); }; void pop_front(const char *fn, int line) { LIST_TRACE; this->std::list::pop_front(); }; void pop_back(const char *fn, int line) { LIST_TRACE; this->std::list::pop_back(); }; void splice(iterator pos, element_list_t &other, iterator first, iterator last, const char *fn, int line) { SPLICE_TRACE; this->std::list::splice(pos, other, first, last); } }; struct element { element() : e_token(DT_INVALID), e_sub_elements(NULL) { }; element(element_list_t &subs, data_token_t token, bool assign_subs_elements = true) : e_capture(subs.front().e_capture.c_begin, subs.back().e_capture.c_end), e_token(token), e_sub_elements(NULL) { if (assign_subs_elements) { this->assign_elements(subs); } }; element(const element &other) { /* require(other.e_sub_elements == NULL); */ this->e_capture = other.e_capture; this->e_token = other.e_token; this->e_sub_elements = NULL; if (other.e_sub_elements != NULL) { this->assign_elements(*other.e_sub_elements); } }; ~element() { if (this->e_sub_elements != NULL) { delete this->e_sub_elements; this->e_sub_elements = NULL; } }; element & operator=(const element &other) { this->e_capture = other.e_capture; this->e_token = other.e_token; this->e_sub_elements = NULL; if (other.e_sub_elements != NULL) { this->assign_elements(*other.e_sub_elements); } return *this; }; void assign_elements(element_list_t &subs) { if (this->e_sub_elements == NULL) { this->e_sub_elements = new element_list_t("_sub_", __FILE__, __LINE__); } this->e_sub_elements->swap(subs); this->update_capture(); }; void update_capture(void) { if (this->e_sub_elements != NULL) { this->e_capture.c_begin = this->e_sub_elements->front().e_capture.c_begin; this->e_capture.c_end = this->e_sub_elements->back().e_capture.c_end; } }; const element & get_pair_value(void) const { require(this->e_token == DNT_PAIR); return this->e_sub_elements->back(); }; data_token_t value_token(void) const { data_token_t retval = DT_INVALID; if (this->e_token == DNT_VALUE) { if (this->e_sub_elements != NULL && this->e_sub_elements->size() == 1) { retval = this->e_sub_elements->front().e_token; } } else { retval = this->e_token; } return retval; }; void print(FILE *out, pcre_input &pi, int offset = 0) { int lpc; if (this->e_sub_elements != NULL) { for (element_list_t::iterator iter2 = this->e_sub_elements->begin(); iter2 != this->e_sub_elements->end(); ++iter2) { iter2->print(out, pi, offset + 1); } } fprintf(out, "%4s %3d:%-3d ", data_scanner::token2name(this->e_token), this->e_capture.c_begin, this->e_capture.c_end); for (lpc = 0; lpc < this->e_capture.c_end; lpc++) { if (lpc == this->e_capture.c_begin) { fputc('^', out); } else if (lpc == (this->e_capture.c_end - 1)) { fputc('^', out); } else if (lpc > this->e_capture.c_begin) { fputc('-', out); } else{ fputc(' ', out); } } for (; lpc < (int)pi.pi_length; lpc++) { fputc(' ', out); } std::string sub = pi.get_substr(&this->e_capture); fprintf(out, " %s\n", sub.c_str()); }; pcre_context::capture_t e_capture; data_token_t e_token; element_list_t * e_sub_elements; }; struct element_cmp { bool operator()(data_token_t token, const element &elem) const { return token == elem.e_token || token == DT_ANY; }; bool operator()(const element &elem, data_token_t token) const { return (*this)(token, elem); }; }; struct element_if { element_if(data_token_t token) : ei_token(token) { }; bool operator()(const element &a) const { return a.e_token == this->ei_token; }; private: data_token_t ei_token; }; data_parser(data_scanner *ds) : dp_errors("dp_errors", __FILE__, __LINE__), dp_pairs("dp_pairs", __FILE__, __LINE__), dp_format(NULL), dp_qualifier(DT_INVALID), dp_separator(DT_INVALID), dp_scanner(ds) { if (TRACE_FILE != NULL) { fprintf(TRACE_FILE, "input %s\n", ds->get_input().get_string()); } }; void pairup(schema_id_t *schema, element_list_t &pairs_out, element_list_t &in_list) { element_list_t ELEMENT_LIST_T(el_stack), ELEMENT_LIST_T(free_row), ELEMENT_LIST_T(key_comps), ELEMENT_LIST_T(value), ELEMENT_LIST_T(prefix); SpookyHash context; POINT_TRACE("pairup_start"); for (element_list_t::iterator iter = in_list.begin(); iter != in_list.end(); ++iter) { if (iter->e_token == DNT_GROUP) { element_list_t ELEMENT_LIST_T(group_pairs); this->pairup(NULL, group_pairs, *iter->e_sub_elements); if (!group_pairs.empty()) { iter->assign_elements(group_pairs); } } if (iter->e_token == this->dp_format->df_terminator) { std::vector key_copy; value.SPLICE(value.end(), key_comps, key_comps.begin(), key_comps.end()); value.remove_if(element_if(this->dp_format->df_terminator)); strip(value, element_if(DT_WHITE)); value.remove_if(element_if(DT_COMMA)); if (!value.empty()) { el_stack.PUSH_BACK(element(value, DNT_VALUE)); } value.clear(); key_comps.PUSH_BACK(*iter); } else if (iter->e_token == this->dp_qualifier) { value.SPLICE(value.end(), key_comps, key_comps.begin(), key_comps.end()); strip(value, element_if(DT_WHITE)); if (!value.empty()) { el_stack.PUSH_BACK(element(value, DNT_VALUE)); } } else if (iter->e_token == this->dp_separator) { element_list_t::iterator key_iter = key_comps.end(); bool found = false; do { --key_iter; if (key_iter->e_token == this->dp_format->df_appender) { ++key_iter; value.SPLICE(value.end(), key_comps, key_comps.begin(), key_iter); key_comps.POP_FRONT(); found = true; } else if (key_iter->e_token == this->dp_format->df_terminator) { std::vector key_copy; value.SPLICE(value.end(), key_comps, key_comps.begin(), key_iter); ++key_iter; key_comps.POP_FRONT(); strip(key_comps, element_if(DT_WHITE)); found = true; } } while (key_iter != key_comps.begin() && !found); if (!found && !el_stack.empty() && !key_comps.empty()) { element_list_t::iterator value_iter; if (el_stack.size() > 1 && this->dp_format->df_appender != DT_INVALID && this->dp_format->df_terminator != DT_INVALID) { /* If we're expecting a terminator and haven't found it */ /* then this is part of the value. */ continue; } value.SPLICE(value.end(), key_comps, key_comps.begin(), key_comps.end()); value_iter = value.end(); std::advance(value_iter, -1); key_comps.SPLICE(key_comps.begin(), value, value_iter, value.end()); key_comps.resize(1); } strip(value, element_if(DT_WHITE)); value.remove_if(element_if(DT_COMMA)); if (!value.empty()) { el_stack.PUSH_BACK(element(value, DNT_VALUE)); } strip(key_comps, element_if(DT_WHITE)); if (!key_comps.empty()) { el_stack.PUSH_BACK(element(key_comps, DNT_KEY, false)); } key_comps.clear(); value.clear(); } else { key_comps.PUSH_BACK(*iter); } POINT_TRACE("pairup_loop"); } POINT_TRACE("pairup_eol"); if (el_stack.empty()) { free_row.SPLICE(free_row.begin(), key_comps, key_comps.begin(), key_comps.end()); } else { value.SPLICE(value.begin(), key_comps, key_comps.begin(), key_comps.end()); value.remove_if(element_if(this->dp_format->df_terminator)); strip(value, element_if(DT_WHITE)); value.remove_if(element_if(DT_COMMA)); if (!value.empty()) { el_stack.PUSH_BACK(element(value, DNT_VALUE)); } } POINT_TRACE("pairup_stack"); context.Init(0, 0); while (!el_stack.empty()) { element_list_t::iterator kv_iter = el_stack.begin(); if (kv_iter->e_token == DNT_VALUE) { if (pairs_out.empty()) { free_row.PUSH_BACK(el_stack.front()); } else { element_list_t ELEMENT_LIST_T(free_pair_subs); struct element blank; blank.e_capture.c_begin = blank.e_capture.c_end = el_stack.front().e_capture. c_begin; blank.e_token = DNT_KEY; free_pair_subs.PUSH_BACK(blank); free_pair_subs.PUSH_BACK(el_stack.front()); pairs_out.PUSH_BACK(element(free_pair_subs, DNT_PAIR)); } } if (kv_iter->e_token != DNT_KEY) { el_stack.POP_FRONT(); continue; } ++kv_iter; if (kv_iter == el_stack.end()) { el_stack.POP_FRONT(); continue; } element_list_t ELEMENT_LIST_T(pair_subs); if (schema != NULL) { size_t key_len; const char *key_val = this->get_element_string(el_stack.front(), key_len); context.Update(key_val, key_len); } while (!free_row.empty()) { element_list_t ELEMENT_LIST_T(free_pair_subs); struct element blank; blank.e_capture.c_begin = blank.e_capture.c_end = free_row.front().e_capture. c_begin; blank.e_token = DNT_KEY; free_pair_subs.PUSH_BACK(blank); free_pair_subs.PUSH_BACK(free_row.front()); pairs_out.PUSH_BACK(element(free_pair_subs, DNT_PAIR)); free_row.POP_FRONT(); } bool has_value = false; if (kv_iter->e_token == DNT_VALUE) { ++kv_iter; has_value = true; } pair_subs.SPLICE(pair_subs.begin(), el_stack, el_stack.begin(), kv_iter); if (!has_value) { element_list_t ELEMENT_LIST_T(blank_value); struct element blank; blank.e_token = DT_QUOTED_STRING; blank.e_capture.c_begin = blank.e_capture.c_end = pair_subs.front().e_capture.c_end; blank_value.PUSH_BACK(blank); pair_subs.PUSH_BACK(element(blank_value, DNT_VALUE)); } pairs_out.PUSH_BACK(element(pair_subs, DNT_PAIR)); } if (pairs_out.size() == 1) { element &pair = pairs_out.front(); element &value = pair.e_sub_elements->back(); if (value.e_token == DNT_VALUE && value.e_sub_elements != NULL && value.e_sub_elements->size() > 1) { element_list_t::iterator next_sub; next_sub = pair.e_sub_elements->begin(); ++next_sub; prefix.SPLICE(prefix.begin(), *pair.e_sub_elements, pair.e_sub_elements->begin(), next_sub); free_row.clear(); free_row.SPLICE(free_row.begin(), *value.e_sub_elements, value.e_sub_elements->begin(), value.e_sub_elements->end()); pairs_out.clear(); context.Init(0, 0); } } if (pairs_out.empty() && !free_row.empty()) { while (!free_row.empty()) { switch (free_row.front().e_token) { case DNT_GROUP: case DNT_VALUE: case DT_EMAIL: case DT_CONSTANT: case DT_NUMBER: case DT_SYMBOL: case DT_HEX_NUMBER: case DT_OCTAL_NUMBER: case DT_VERSION_NUMBER: case DT_QUOTED_STRING: case DT_IPV4_ADDRESS: case DT_IPV6_ADDRESS: case DT_MAC_ADDRESS: case DT_HEX_DUMP: case DT_UUID: case DT_URL: case DT_PATH: case DT_DATE: case DT_TIME: case DT_PERCENTAGE: { element_list_t ELEMENT_LIST_T(pair_subs); struct element blank; blank.e_capture.c_begin = blank.e_capture.c_end = free_row.front().e_capture. c_begin; blank.e_token = DNT_KEY; pair_subs.PUSH_BACK(blank); pair_subs.PUSH_BACK(free_row.front()); pairs_out.PUSH_BACK(element(pair_subs, DNT_PAIR)); // Throw something into the hash so that the number of // columns is significant. I don't think we want to // use the token ID since some columns values might vary // between rows. context.Update(" ", 1); } break; case DT_WHITE: break; default: { size_t key_len; const char *key_val = this->get_element_string( free_row.front(), key_len); context.Update(key_val, key_len); } break; } free_row.POP_FRONT(); } } if (!prefix.empty()) { element_list_t ELEMENT_LIST_T(pair_subs); struct element blank; blank.e_capture.c_begin = blank.e_capture.c_end = prefix.front().e_capture.c_begin; blank.e_token = DNT_KEY; pair_subs.PUSH_BACK(blank); pair_subs.PUSH_BACK(prefix.front()); pairs_out.PUSH_FRONT(element(pair_subs, DNT_PAIR)); } if (schema != NULL) { context.Final(this->dp_schema_id.out(0), this->dp_schema_id.out(1)); } }; void discover_format(void) { pcre_context_static<30> pc; int hist[DT_TERMINAL_MAX]; struct element elem; this->dp_group_token.push_back(DT_INVALID); this->dp_group_stack.resize(1); this->dp_qualifier = DT_INVALID; this->dp_separator = DT_COLON; data_format_state_t prefix_state = DFS_INIT; data_format_state_t semi_state = DFS_INIT; data_format_state_t comma_state = DFS_INIT; memset(hist, 0, sizeof(hist)); while (this->dp_scanner->tokenize(pc, elem.e_token)) { pcre_context::iterator pc_iter; pc_iter = std::find_if(pc.begin(), pc.end(), capture_if_not(-1)); require(pc_iter != pc.end()); elem.e_capture = *pc_iter; require(elem.e_capture.c_begin != -1); require(elem.e_capture.c_end != -1); prefix_state = dfs_prefix_next(prefix_state, elem.e_token); semi_state = dfs_semi_next(semi_state, elem.e_token); comma_state = dfs_comma_next(comma_state, elem.e_token); if (prefix_state != DFS_ERROR) { if (semi_state == DFS_ERROR) { semi_state = DFS_INIT; } if (comma_state == DFS_ERROR) { comma_state = DFS_INIT; } } hist[elem.e_token] += 1; switch (elem.e_token) { case DT_LPAREN: case DT_LANGLE: case DT_LCURLY: case DT_LSQUARE: this->dp_group_token.push_back(elem.e_token); this->dp_group_stack.push_back(element_list_t("_anon_", __FILE__, __LINE__)); break; case DT_RPAREN: case DT_RANGLE: case DT_RCURLY: case DT_RSQUARE: if (this->dp_group_token.back() == (elem.e_token - 1)) { this->dp_group_token.pop_back(); std::list::reverse_iterator riter = this->dp_group_stack.rbegin(); ++riter; if (!this->dp_group_stack.back().empty()) { (*riter).PUSH_BACK(element(this->dp_group_stack.back(), DNT_GROUP)); } this->dp_group_stack.pop_back(); } else { this->dp_group_stack.back().PUSH_BACK(elem); } break; default: this->dp_group_stack.back().PUSH_BACK(elem); break; } } while (this->dp_group_stack.size() > 1) { this->dp_group_token.pop_back(); std::list::reverse_iterator riter = this->dp_group_stack.rbegin(); ++riter; if (!this->dp_group_stack.back().empty()) { (*riter).PUSH_BACK(element(this->dp_group_stack.back(), DNT_GROUP)); } this->dp_group_stack.pop_back(); } if (hist[DT_EQUALS]) { this->dp_qualifier = DT_COLON; this->dp_separator = DT_EQUALS; } if (semi_state != DFS_ERROR && hist[DT_SEMI]) { this->dp_format = &FORMAT_SEMI; } else if (comma_state != DFS_ERROR) { this->dp_format = &FORMAT_COMMA; } else { this->dp_format = &FORMAT_PLAIN; } }; void parse(void) { this->discover_format(); this->pairup(&this->dp_schema_id, this->dp_pairs, this->dp_group_stack.front()); }; std::string get_element_string(const element &elem) const { pcre_input &pi = this->dp_scanner->get_input(); return pi.get_substr(&elem.e_capture); }; const char *get_element_string(const element &elem, size_t &len_out) { pcre_input &pi = this->dp_scanner->get_input(); len_out = elem.e_capture.length(); return pi.get_substr_start(&elem.e_capture); }; void print(FILE *out, element_list_t &el) { fprintf(out, " %s\n", this->dp_scanner->get_input().get_string()); for (element_list_t::iterator iter = el.begin(); iter != el.end(); ++iter) { iter->print(out, this->dp_scanner->get_input()); } }; std::vector dp_group_token; std::list dp_group_stack; element_list_t dp_errors; element_list_t dp_pairs; schema_id_t dp_schema_id; data_format * dp_format; data_token_t dp_qualifier; data_token_t dp_separator; private: data_scanner *dp_scanner; }; #endif lnav-0.7.0/src/data_scanner.cc000664 000765 000024 00000024100 12313321533 016441 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include "pcrepp.hh" #include "data_scanner.hh" using namespace std; static struct { const char *name; pcrepp pcre; } MATCHERS[DT_TERMINAL_MAX] = { { "quot", pcrepp("\\A(?:(?:u|r)?\"((?:\\\\.|[^\"])+)\"|" "(?:u|r)?'((?:\\\\.|[^'])+)')"), }, { "url", pcrepp("\\A([\\w]+://[^\\s'\"\\[\\](){}]+[/a-zA-Z0-9\\-=&])"), }, { "path", pcrepp("\\A((?:/|\\./|\\.\\./)[\\w\\.\\-_\\~/]*)"), }, { "mac", pcrepp( "\\A([0-9a-fA-F][0-9a-fA-F](?::[0-9a-fA-F][0-9a-fA-F]){5})(?!:)"), }, { "date", pcrepp("\\A(" "\\d{4}/\\d{1,2}/\\d{1,2}|" "\\d{4}-\\d{1,2}-\\d{1,2}|" "\\d{2}/\\w{3}/\\d{4}" ")T?"), }, { "time", pcrepp( "\\A([\\s\\d]\\d:\\d\\d(?:(?!:\\d)|:\\d\\d(?:\\.\\d{3,6})?Z?))\\b"), }, /* { "qual", pcrepp("\\A([^\\s:=]+:[^\\s:=,]+(?!,)(?::[^\\s:=,]+)*)"), }, */ { "ipv6", pcrepp("\\A(::|[:\\da-fA-f\\.]+[a-fA-f\\d](?:%\\w+)?)"), }, { "hexd", pcrepp( "\\A([0-9a-fA-F][0-9a-fA-F](?::[0-9a-fA-F][0-9a-fA-F])+)"), }, { "coln", pcrepp("\\A(:)"), }, { "eq", pcrepp("\\A(=)"), }, { "comm", pcrepp("\\A(,)"), }, { "semi", pcrepp("\\A(;)"), }, { "lcurly", pcrepp("\\A({)"), }, { "rcurly", pcrepp("\\A(})"), }, { "lsquare", pcrepp("\\A(\\[)"), }, { "rsquare", pcrepp("\\A(\\])"), }, { "lparen", pcrepp("\\A(\\()"), }, { "rparen", pcrepp("\\A(\\))"), }, { "langle", pcrepp("\\A(\\<)"), }, { "rangle", pcrepp("\\A(\\>)"), }, { "ipv4", pcrepp("\\A(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})"), }, { "uuid", pcrepp( "\\A([0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12})"), }, { "vers", pcrepp( "\\A(" "[0-9]+(?:\\.[0-9]+\\w*){2,}(?:-\\w+)?|" "[0-9]+(?:\\.[0-9]+\\w*)+-\\w+?" ")\\b"), }, { "oct", pcrepp("\\A(-?0[0-7]+\\b)"), }, { "pcnt", pcrepp("\\A(-?[0-9]+(\\.[0-9]+)?[ ]*%\\b)"), }, { "num", pcrepp("\\A(-?[0-9]+(\\.[0-9]+)?([eE][-+][0-9]+)?)" "\\b(?![\\._\\-][a-zA-Z])"), }, { "hex", pcrepp("\\A(-?(?:0x|[0-9])[0-9a-fA-F]+)" "\\b(?![\\._\\-][a-zA-Z])"), }, { "mail", pcrepp( "\\A([a-zA-Z0-9\\._%+-]+@[a-zA-Z0-9\\.-]+\\.[a-zA-Z]+)\\b"), }, { "cnst", pcrepp("\\A(true|True|TRUE|false|False|FALSE|None|null)\\b") }, { "word", pcrepp( "\\A([a-zA-Z][a-z']+(?=[\\s\\(\\)!\\*:;'\\\"\\?,]|[\\.\\!,\\?]\\s|$))"), }, { "sym", pcrepp( "\\A([^\";\\s:=,\\(\\)\\{\\}\\[\\]\\+#!@%\\^&\\*'\\?<>\\~`\\|\\\\]+" "(?:::[^\";\\s:=,\\(\\)\\{\\}\\[\\]\\+#!@%\\^&\\*'\\?<>\\~`\\|\\\\]+)*)"), }, { "line", pcrepp("\\A(\r?\n|\r|;)"), }, { "wspc", pcrepp("\\A([ \\r\\t\\n]+)"), }, { "dot", pcrepp("\\A(\\.)"), }, { "gbg", pcrepp("\\A(.)"), }, }; const char *DNT_NAMES[DNT_MAX - DNT_KEY] = { "key", "pair", "val", "row", "unit", "meas", "var", "rang", "dt", "grp", }; const char *data_scanner::token2name(data_token_t token) { if (token < 0) { return "inv"; } else if (token < DT_TERMINAL_MAX) { return MATCHERS[token].name; } else if (token == DT_ANY) { return "any"; } else{ return DNT_NAMES[token - DNT_KEY]; } } static bool find_string_end(const char *str, size_t &start, size_t length, char term) { for (; start < length; start++) { if (str[start] == term) { start += 1; return true; } if (str[start] == '\\') { if (start + 1 >= length) { return false; } start += 1; } } return false; } static void single_char_capture(pcre_context &pc, pcre_input &pi) { pc.all()[0].c_begin = pi.pi_offset; pc.all()[0].c_end = pi.pi_offset + 1; pc.all()[1] = pc.all()[0]; pc.set_count(2); pi.pi_next_offset = pi.pi_offset + 1; } bool data_scanner::tokenize(pcre_context &pc, data_token_t &token_out) { const char *str = this->ds_pcre_input.get_string(); pcre_input &pi = this->ds_pcre_input; int lpc; token_out = data_token_t(-1); if (this->ds_pcre_input.pi_next_offset > this->ds_pcre_input.pi_length) { return false; } else if (this->ds_pcre_input.pi_next_offset == this->ds_pcre_input.pi_length) { this->ds_pcre_input.pi_next_offset += 1; token_out = DT_LINE; return false; } for (lpc = 0; lpc < DT_TERMINAL_MAX; lpc++) { switch (lpc) { case DT_QUOTED_STRING: { pcre_input &pi = this->ds_pcre_input; const char *str = pi.get_string(); size_t str_start, str_end; bool found = false; pi.pi_offset = pi.pi_next_offset; str_end = str_start = pi.pi_offset + 1; switch (str[pi.pi_offset]) { case 'u': case 'r': if (pi.pi_offset + 1 < pi.pi_length && (str[pi.pi_offset + 1] == '\'' || str[pi.pi_offset + 1] == '\"')) { str_start += 1; str_end += 1; found = find_string_end(str, str_end, pi.pi_length, str[pi.pi_offset + 1]); } break; case '\'': case '\"': found = find_string_end(str, str_end, pi.pi_length, str[pi.pi_offset]); break; } if (found) { token_out = data_token_t(DT_QUOTED_STRING); pi.pi_next_offset = str_end; pc.all()[0].c_begin = pi.pi_offset; pc.all()[0].c_end = str_end; pc.all()[1].c_begin = str_start; pc.all()[1].c_end = str_end - 1; pc.set_count(2); return true; } } break; case DT_COLON: { pi.pi_offset = pi.pi_next_offset; if (str[pi.pi_offset] == ':') { token_out = data_token_t(DT_COLON); single_char_capture(pc, pi); return true; } } break; case DT_EQUALS: { pi.pi_offset = pi.pi_next_offset; if (str[pi.pi_offset] == '=') { token_out = data_token_t(DT_EQUALS); single_char_capture(pc, pi); return true; } } break; case DT_COMMA: { pi.pi_offset = pi.pi_next_offset; if (str[pi.pi_offset] == ',') { token_out = data_token_t(DT_COMMA); single_char_capture(pc, pi); return true; } } break; case DT_SEMI: { pi.pi_offset = pi.pi_next_offset; if (str[pi.pi_offset] == ';') { token_out = data_token_t(DT_SEMI); single_char_capture(pc, pi); return true; } } break; default: if (MATCHERS[lpc].pcre.match(pc, this->ds_pcre_input, PCRE_ANCHORED)) { switch (lpc) { case DT_IPV6_ADDRESS: if (pc.all()->length() <= INET6_ADDRSTRLEN) { char in6str[INET6_ADDRSTRLEN]; char buf[sizeof(struct in6_addr)]; this->ds_pcre_input.get_substr(pc.all(), in6str); if (inet_pton(AF_INET6, in6str, buf) == 1) { token_out = data_token_t(lpc); return true; } } this->ds_pcre_input.pi_next_offset = this->ds_pcre_input.pi_offset; break; default: token_out = data_token_t(lpc); return true; } } break; } } ensure((0 <= token_out && token_out < DT_TERMINAL_MAX)); return true; } lnav-0.7.0/src/data_scanner.hh000664 000765 000024 00000006600 12307146044 016465 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __data_scanner_hh #define __data_scanner_hh #include #include "pcrepp.hh" #include "shared_buffer.hh" enum data_token_t { DT_INVALID = -1, DT_QUOTED_STRING = 0, DT_URL, DT_PATH, DT_MAC_ADDRESS, DT_DATE, DT_TIME, DT_IPV6_ADDRESS, DT_HEX_DUMP, /* DT_QUALIFIED_NAME, */ DT_COLON, DT_EQUALS, DT_COMMA, DT_SEMI, DT_LCURLY, DT_RCURLY, DT_LSQUARE, DT_RSQUARE, DT_LPAREN, DT_RPAREN, DT_LANGLE, DT_RANGLE, DT_IPV4_ADDRESS, DT_UUID, DT_VERSION_NUMBER, DT_OCTAL_NUMBER, DT_PERCENTAGE, DT_NUMBER, DT_HEX_NUMBER, DT_EMAIL, DT_CONSTANT, DT_WORD, DT_SYMBOL, DT_LINE, DT_WHITE, DT_DOT, DT_GARBAGE, DT_TERMINAL_MAX = DT_GARBAGE + 1, DNT_KEY = 50, DNT_PAIR, DNT_VALUE, DNT_ROW, DNT_UNITS, DNT_MEASUREMENT, DNT_VARIABLE_KEY, DNT_ROWRANGE, DNT_DATE_TIME, DNT_GROUP, DNT_MAX, DT_ANY = 100, }; class data_scanner { public: static const char *token2name(data_token_t token); data_scanner(const std::string &line, size_t off = 0, size_t len = -1) : ds_line(line), ds_pcre_input(ds_line.c_str(), off, len) { if (!line.empty() && line[line.length() - 1] == '.') { this->ds_pcre_input.pi_length -= 1; } }; data_scanner(shared_buffer_ref &line, size_t off = 0, size_t len = -1) : ds_sbr(line), ds_pcre_input(line.get_data(), off, len) { if (line.length() > 0 && line.get_data()[line.length() - 1] == '.') { this->ds_pcre_input.pi_length -= 1; } }; bool tokenize(pcre_context &pc, data_token_t &token_out); pcre_input &get_input() { return this->ds_pcre_input; }; private: std::string ds_line; shared_buffer_ref ds_sbr; pcre_input ds_pcre_input; }; #endif lnav-0.7.0/src/db_sub_source.cc000664 000765 000024 00000003147 12307601632 016651 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "db_sub_source.hh" const char *db_label_source::NULL_STR = ""; lnav-0.7.0/src/db_sub_source.hh000664 000765 000024 00000017316 12307601632 016666 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __db_sub_source_hh #define __db_sub_source_hh #include #include #include #include "listview_curses.hh" #include "hist_source.hh" #include "log_vtab_impl.hh" class db_label_source : public hist_source::label_source { public: db_label_source() { }; ~db_label_source() { }; void hist_label_for_group(int group, std::string &label_out) { label_out.clear(); }; void hist_label_for_bucket(int bucket_start_value, const hist_source::bucket_t &bucket, std::string &label_out) { /* * start_value is the result rowid, each bucket type is a column value * label_out should be the raw text output. */ label_out.clear(); if (bucket_start_value >= (int)this->dls_rows.size()) { return; } for (int lpc = 0; lpc < (int)this->dls_rows[bucket_start_value].size(); lpc++) { int padding = (this->dls_column_sizes[lpc] - strlen(this->dls_rows[bucket_start_value][lpc]) - 1); if (this->dls_column_types[lpc] != SQLITE3_TEXT) { label_out.append(padding, ' '); } label_out.append(this->dls_rows[bucket_start_value][lpc]); if (this->dls_column_types[lpc] == SQLITE3_TEXT) { label_out.append(padding, ' '); } label_out.append(1, ' '); } }; void hist_attrs_for_bucket(int bucket_start_value, const hist_source::bucket_t &bucket, string_attrs_t &sa) { struct line_range lr(0, 0); struct line_range lr2(0, -1); if (bucket_start_value >= (int)this->dls_rows.size()) { return; } for (size_t lpc = 0; lpc < this->dls_column_sizes.size() - 1; lpc++) { if (bucket_start_value % 2 == 0) { sa.push_back(string_attr(lr2, &view_curses::VC_STYLE, A_BOLD)); } lr.lr_start += this->dls_column_sizes[lpc] - 1; lr.lr_end = lr.lr_start + 1; sa.push_back(string_attr(lr, &view_curses::VC_GRAPHIC, ACS_VLINE)); lr.lr_start += 1; } } /* TODO: add support for left and right justification... numbers should */ /* be right justified and strings should be left. */ void push_column(const char *colstr) { int index = this->dls_rows.back().size(); if (colstr == NULL) { colstr = NULL_STR; } else { colstr = strdup(colstr); if (colstr == NULL) { throw "out of memory"; } } this->dls_rows.back().push_back(colstr); if (this->dls_rows.back().size() > this->dls_column_sizes.size()) { this->dls_column_sizes.push_back(1); } this->dls_column_sizes[index] = std::max(this->dls_column_sizes[index], strlen(colstr) + 1); }; void push_header(const std::string &colstr, int type, bool graphable) { int index = this->dls_headers.size(); this->dls_headers.push_back(colstr); if (this->dls_headers.size() > this->dls_column_sizes.size()) { this->dls_column_sizes.push_back(1); } this->dls_column_sizes[index] = std::max(this->dls_column_sizes[index], colstr.length() + 1); this->dls_column_types.push_back(type); this->dls_headers_to_graph.push_back(graphable); } void clear(void) { this->dls_headers.clear(); this->dls_headers_to_graph.clear(); this->dls_column_types.clear(); for (int row = 0; row < this->dls_rows.size(); row++) { for (int col = 0; col < this->dls_rows[row].size(); col++) { if (this->dls_rows[row][col] != NULL_STR) { free((void *)this->dls_rows[row][col]); } } } this->dls_rows.clear(); this->dls_column_sizes.clear(); } std::string dls_stmt_str; std::vector dls_headers; std::vector dls_headers_to_graph; std::vector dls_column_types; std::vector > dls_rows; std::vector dls_column_sizes; static const char *NULL_STR; }; class db_overlay_source : public list_overlay_source { public: db_overlay_source() : dos_labels(NULL) { }; size_t list_overlay_count(const listview_curses &lv) { return 1; }; bool list_value_for_overlay(const listview_curses &lv, vis_line_t y, attr_line_t &value_out) { view_colors &vc = view_colors::singleton(); if (y != 0) { return false; } std::string & line = value_out.get_string(); db_label_source *dls = this->dos_labels; string_attrs_t &sa = value_out.get_attrs(); for (size_t lpc = 0; lpc < this->dos_labels->dls_column_sizes.size(); lpc++) { int before, total_fill = dls->dls_column_sizes[lpc] - dls->dls_headers[lpc].length(); struct line_range header_range(line.length(), line.length() + dls->dls_column_sizes[lpc]); int attrs = vc.attrs_for_role(this->dos_hist_source->get_role_for_type( bucket_type_t( lpc))) | A_UNDERLINE; if (!this->dos_labels->dls_headers_to_graph[lpc]) { attrs = A_UNDERLINE; } sa.push_back(string_attr(header_range, &view_curses::VC_STYLE, attrs)); before = total_fill / 2; total_fill -= before; line.append(before, ' '); line.append(dls->dls_headers[lpc]); line.append(total_fill, ' '); } struct line_range lr(0); sa.push_back(string_attr(lr, &view_curses::VC_STYLE, A_BOLD | A_UNDERLINE)); return true; }; db_label_source *dos_labels; hist_source * dos_hist_source; }; #endif lnav-0.7.0/src/default-log-formats-json.hh000664 000765 000024 00000003504 12211635053 020663 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file default-log-formats-json.hh */ #ifndef __default_log_formats_json_hh #define __default_log_formats_json_hh extern "C" { /** * The value for this comes from the "default-log-formats.json" file, * which gets linked into the executable by the Makefile. */ extern const char default_log_formats_json[]; } #endif lnav-0.7.0/src/default-log-formats.json000664 000765 000024 00000046205 12312270152 020270 0ustar00stackstaff000000 000000 { "access_log" : { "title" : "Common Access Log", "description" : "The default web access log format for servers like Apache.", "url" : "http://en.wikipedia.org/wiki/Common_Log_Format", "regex" : { "ts-first-noquotes" : { "pattern" : "^(?\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?) (?[^ ]+) (?[^ ]+) (?[A-Z]+) (?[^ \\?]+)(?:\\?(?[^ ]*))? (?:-1|\\d+) (?\\d+) \\d+" }, "ts-first" : { "pattern" : "^(?\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?) (?[^ ]+) (?[^ ]+) (?[A-Z]+) \"(?[^ \\?]+)(?:\\?(?[^ ]*))?\" (?:-1|\\d+) (?\\d+) \\d+" }, "std" : { "pattern" : "^(?[\\w\\.:\\-]+) [\\w\\.\\-]+ (?\\S+) \\[(?[^\\]]+)\\] \"(?:\\-|(?\\w+) (?[^ \\?]+)(?:\\?(?[^ ]*))? (?[\\w/\\.]+))\" (?\\d+) (?\\d+|-)(?: \"(?[^\"]+)\" \"(?[^\"]+)\")?.*" } }, "level-field": "sc_status", "level" : { "error" : "^[^123]" }, "value" : { "c_ip" : { "kind" : "string", "collate" : "ipaddress", "identifier" : true }, "cs_username" : { "kind" : "string", "identifier" : true }, "cs_method" : { "kind" : "string", "identifier" : true }, "cs_uri_stem" : { "kind" : "string", "identifier" : true }, "cs_uri_query" : { "kind" : "string" }, "cs_version" : { "kind" : "string", "identifier" : true }, "sc_status" : { "kind" : "integer", "foreign-key" : true }, "sc_bytes" : { "kind" : "integer" }, "cs_referer" : { "kind" : "string", "identifier" : true }, "cs_user_agent" : { "kind" : "string", "identifier" : true } }, "sample" : [ { "line" : "10.112.72.172 - - [11/Feb/2013:06:43:36 +0000] \"GET /client/ HTTP/1.1\" 200 5778 \"-\" \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17\"" } ] }, "block_log" : { "title" : "Generic Block", "description" : "A generic format for logs, like cron, that have a date at the start of a block.", "regex" : { "std" : { "pattern" : "^(?\\w{3} \\w{3}\\s+\\d{1,2} \\d{2}:\\d{2}:\\d{2} \\w+ \\d{4})$" } }, "sample" : [ { "line" : "Sat Apr 27 03:33:07 PDT 2013" } ] }, "choose_repo_log" : { "title" : "Yum choose_repo Log", "description" : "The log format for the yum choose_repo tool.", "regex" : { "std" : { "pattern" : "^\\[(?\\w+):[^\\]]+] [^:]+:\\d+ (?\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}(?:[\\.,]\\d{3})?):(?.*)" } }, "level-field" : "level", "level" : { "error" : "ERROR", "debug" : "DEBUG", "info" : "INFO", "warning" : "WARNING" }, "sample" : [ { "line": "[INFO:choose_repo] choose_repo:47 2013-06-20 17:26:10,691: Setting region in redhat-rhui.repo" } ] }, "dpkg_log" : { "title" : "Dpkg Log", "description" : "The debian dpkg log.", "regex" : { "std" : { "pattern" : "^(?\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?) (?:(?:(?startup|status|configure|install|upgrade|trigproc|remove|purge)(?: (?config-files|failed-config|half-configured|half-installed|installed|not-installed|post-inst-failed|removal-failed|triggers-awaited|triggers-pending|unpacked))? (?[^ ]+) (?[^ ]+)(?: (?[^ ]+))?)|update-alternatives: (?.*))$" } }, "value" : { "action" : { "kind" : "string", "identifier" : true }, "status" : { "kind" : "string", "identifier" : true }, "package" : { "kind" : "string", "identifier" : true }, "installed_version" : { "kind" : "string" }, "available_version" : { "kind" : "string" } }, "sample" : [ { "line" : "2012-02-14 10:44:10 configure base-files 5.0.0ubuntu20 5.0.0ubuntu20" }, { "line" : "2012-02-14 10:44:30 status unpacked rsyslog 4.2.0-2ubuntu8" }, { "line" : "2012-02-14 10:44:32 update-alternatives: run with --install /usr/bin/rview rview /usr/bin/vim.tiny 10" } ] }, "error_log" : { "title" : "Common Error Log", "description" : "The default web error log format for servers like Apache.", "regex" : { "cups" : { "pattern" : "^(?\\w) \\[(?[^\\]]+)\\] (?.*)" } }, "level-field": "level", "level" : { "error" : "E", "warning" : "W", "info" : "I" }, "sample" : [ { "line" : "E [08/Jun/2013:11:28:58 -0700] Unknown directive BrowseOrder on line 22 of /private/etc/cups/cupsd.conf." } ] }, "fsck_hfs_log" : { "title" : "Fsck_hfs Log", "description" : "Log for the fsck_hfs tool on Mac OS X.", "regex" : { "std" : { "pattern" : "^(?[^:]+): fsck_hfs run at (?\\w{3} \\w{3}\\s+\\d{1,2} \\d{2}:\\d{2}:\\d{2} \\d{4})" } }, "value" : { "device" : { "kind" : "string", "identifier" : true } }, "sample" : [ { "line" : "/dev/rdisk0s2: fsck_hfs run at Wed Jul 25 23:01:18 2012" } ] }, "glog_log" : { "title" : "Glog", "description" : "The google glog format.", "url" : "https://code.google.com/p/google-glog/", "regex" : { "std" : { "pattern" : "^(?[IWECF])(?\\d{4} \\d{2}:\\d{2}:\\d{2}\\.\\d{6}) (?\\d+) (?[^:]+):(?\\d+)\\] (?(?:.|\\n)*)" } }, "level-field" : "level", "level" : { "error" : "E", "warning" : "W", "info" : "I", "critical" : "C", "fatal" : "F" }, "value" : { "thread" : { "kind" : "integer", "identifier" : true, "foreign-key" : true }, "src_file" : { "kind" : "string", "identifier" : true }, "src_line" : { "kind" : "integer", "foreign-key" : true } }, "sample" : [ { "line" : "E0517 15:04:22.619632 1952452992 logging_unittest.cc:253] Log every 3, iteration 19" } ] }, "page_log" : { "title" : "CUPS Page Log", "description" : "The CUPS server log of printed pages.", "url" : "http://www.cups.org/documentation.php/doc-1.7/ref-page_log.html", "regex" : { "pre-1.7" : { "pattern" : "^(?[\\w_\\-\\.]+) (?[\\w\\.\\-]+) (?\\d+) \\[(?[^\\]]+)\\] (?total|\\d+) (?\\d+) (?[^ ]+) (?[\\w\\.:\\-]+)$" }, "1.7" : { "pattern" : "^(?[\\w_\\-\\.]+) (?[\\w\\.\\-]+) (?\\d+) \\[(?[^\\]]+)\\] (?total|\\d+) (?\\d+) (?[^ ]+) (?[\\w\\.:\\-]+) (?.+) (?[^ ]+) (?.+)$" } }, "value" : { "printer" : { "kind" : "string", "identifier" : true }, "username" : { "kind" : "string", "identifier" : true }, "job_id" : { "kind" : "integer", "identifier" : true }, "page_number" : { "kind" : "string" }, "num_copies" : { "kind" : "integer" }, "job_billing" : { "kind" : "string", "identifier" : true }, "job_originating_hostname" : { "kind" : "string", "collate" : "ipaddress", "identifier" : true }, "job_name" : { "kind" : "string", "identifier" : true }, "media" : { "kind" : "string", "identifier" : true }, "sides" : { "kind" : "string", "identifier" : true } }, "sample" : [ { "line" : "Photosmart_7520_series stack 11 [18/May/2013:13:21:15 -0700] total 0 - localhost 5615311548-159003235-tickets.pdf Letter one-sided" }, { "line" : "tec_IS2027 kurt 401 [22/Apr/2003:10:28:43 +0100] 1 3 #marketing 10.160.50.13" } ] }, "snaplogic_log" : { "title" : "SnapLogic Server Log", "description" : "The SnapLogic server log format.", "url" : "http://www.snaplogic.com/docs/user-guide/user-guide.htm", "regex" : { "std" : { "pattern" : "^(?\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?) (?:(?:(?\\w{4,}) (?[^ ]+) (?[^ ]+) (?[^ ]+) (?-|\\d+)(?:\\.(?[^ ]+))? (?[^ ]+) (?[^ ]+))|(?:(?:stdout|stderr): ))(?.*)" } }, "level-field" : "level", "level" : { "error" : "ERROR", "debug" : "DEBUG", "info" : "INFO", "warning" : "WARNING" }, "value" : { "logger" : { "kind" : "string", "identifier" : true }, "facility" : { "kind" : "string", "identifier" : true }, "msgid" : { "kind" : "string", "identifier" : true }, "pipe_rid" : { "kind" : "string", "identifier" : true }, "comp_rid" : { "kind" : "string", "identifier" : true }, "resource_name" : { "kind" : "string", "identifier" : true }, "invoker" : { "kind" : "string", "identifier" : true } }, "sample" : [ { "line" : "2013-07-30T09:40:25 DEBUG main_process.main PM - 1768839331504132353247612213662950165988626018 - - Pipeline manager '' sending to Leads. Invoker 'admin': PREPARE {'parent_rid': '1768839331504132353247612213662950165988626018', 'resource_name': u'Leads', 'input_views': {}, 'parameters': {u'DELIMITER': u',', u'INPUTFILE': u'file://tutorial/data/leads.csv'}, 'output_views': {u'Output1': {'method': 'GET'}}, 'context_name': u'', 'snap_control_version': '1.2'}" } ] }, "syslog_log" : { "title" : "Syslog", "description" : "The system logger format found on most posix systems.", "url" : "http://en.wikipedia.org/wiki/Syslog", "regex" : { "std" : { "pattern" : "^(?\\w{3}\\s+\\d{1,2} \\d{2}:\\d{2}:\\d{2})(?: (?[a-zA-Z0-9:][^ ]+[a-zA-Z0-9]))?(?:(?: (?(?:[^\\[:]+|[^:]+))(?:\\[(?\\d+)])?:(?(?:.|\\n)*))$|:?(?:(?: ---)? last message repeated \\d+ times?(?: ---)?))" } }, "level-field" : "body", "level" : { "error" : "(?:failed|failure|error)", "warning" : "(?:warn|not responding|init: cannot execute)" }, "value" : { "log_hostname" : { "kind" : "string", "collate" : "ipaddress", "identifier" : true }, "log_procname" : { "kind" : "string", "identifier" : true }, "log_pid" : { "kind" : "string", "identifier" : true, "action-list" : ["dump_pid"] } }, "action" : { "dump_pid" : { "label" : "Show Process Info", "capture-output" : true, "cmd" : ["dump-pid.sh"] } }, "sample" : [ { "line" : "Jun 27 01:47:20 Tims-MacBook-Air.local configd[17]: network changed: v4(en0-:192.168.1.8) DNS- Proxy- SMB" }, { "line" : "Jun 20 17:26:13 ip-10-188-149-5 [CLOUDINIT] util.py[DEBUG]: Restoring selinux mode for /var/lib/cloud (recursive=False)" } ] }, "tcsh_history" : { "title" : "TCSH History", "description" : "The tcsh history file format.", "convert-to-local-time" : true, "regex" : { "std" : { "pattern" : "^#(?\\+\\d+)\\n?(?.*)?$" } }, "sample" : [ { "line" : "#+1375138067\necho HELLO=BAR" } ] }, "uwsgi_log" : { "title" : "Uwsgi Log", "description" : "The uwsgi log format.", "regex" : { "std" : { "pattern" : "^\\[pid: (?\\d+)\\|app: (?[\\-\\d]+)\\|req: (?[\\-\\d]+)/(?\\d+)\\] (?[^ ]+) \\((?[^\\)]*)\\) \\{(?\\d+) vars in (?\\d+) bytes\\} \\[(?[^\\]]+)\\] (?[A-Z]+) (?[^ \\?]+)(?:\\?(?[^ ]*))? => generated (?\\d+) bytes in (?\\d+) (?\\w+) \\((?[^ ]+) (?\\d+)\\) (?\\d+) headers in (?\\d+) bytes \\((?\\d+) switches on core (?\\d+)\\)" } }, "level-field": "sc_status", "level" : { "error" : "^[^123]" }, "value" : { "s_pid" : { "kind" : "string", "identifier" : true }, "s_app" : { "kind" : "string", "identifier" : true }, "s_req" : { "kind" : "integer" }, "s_worker_reqs" : { "kind" : "integer" }, "c_ip" : { "kind" : "string", "collate" : "ipaddress", "identifier" : true }, "cs_username" : { "kind" : "string", "identifier" : true }, "cs_vars" : { "kind" : "integer" }, "cs_bytes" : { "kind" : "integer" }, "cs_method" : { "kind" : "string", "identifier" : true }, "cs_uri_stem" : { "kind" : "string", "identifier" : true }, "cs_uri_query" : { "kind" : "string" }, "sc_bytes" : { "kind" : "integer" }, "s_runtime" : { "kind" : "float", "unit" : { "field" : "rt_unit", "scaling-factor" : { "/msecs" : 1000.0, "/micros" : 1000000.0 } } }, "cs_version" : { "kind" : "string", "identifier" : true }, "sc_status" : { "kind" : "integer", "foreign-key" : true }, "sc_headers" : { "kind" : "integer" }, "sc_header_bytes" : { "kind" : "integer" }, "s_switches" : { "kind" : "integer" }, "s_core" : { "kind" : "string", "identifier" : true } }, "sample" : [ { "line" : "[pid: 24386|app: 0|req: 482950/4125645] 86.221.170.65 () {44 vars in 1322 bytes} [Tue Jan 3 05:01:31 2012] GET /contest/log_presence/shhootter/?_=1325592089910 => generated 192 bytes in 21 msecs (HTTP/1.1 200) 4 headers in 188 bytes (1 switches on core 0)" } ] }, "vmw_log" : { "title" : "VMware Logs", "description" : "One of the log formats used in VMware's ESXi and vCenter software.", "url" : "http://kb.vmware.com/kb/2004201", "regex" : { "5.0+" : { "pattern" : "^(?\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z) \\[(?\\w+) (?\\w+) '(?[^']+)'(?: opID=(?[^ \\]]+))?(?: user=(?[\\w\\-]+))?\\](?.*)$" }, "pre-5.0" : { "pattern" : "^\\[(?\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}) (?\\w+) (?\\w+) '(?[^']+)'(?: opID=(?[^ \\]]+))?(?: user=(?[\\w\\-]+))?\\](?.*)$" } }, "level-field": "level", "level" : { "error" : "error", "warning" : "warning", "trace" : "verbose" }, "value" : { "tid" : { "kind" : "string", "identifier" : true }, "comp" : { "kind" : "string", "identifier" : true }, "opid" : { "kind" : "string", "identifier" : true }, "user" : { "kind" : "string", "identifier" : true } }, "sample" : [ { "line" : "[2011-04-01 15:14:34.203 F5A5AB90 info 'vm:/vmfs/volumes/4d6579ec-23f981cb-465c-00237da0cfee/Vmotion-test/Vmotion-test.vmx' opID=F6FC49D5-000007E6-d] VMotionPrepare: dstMgmtIp=10.21.49.138" } ] } } lnav-0.7.0/src/dump-pid.sh000755 000765 000024 00000000422 12221552624 015572 0ustar00stackstaff000000 000000 #!/bin/sh IN_PID=`cat` if test "${IN_PID}" -gt 0 > /dev/null 2>&1 && \ kill -0 $IN_PID > /dev/null 2>&1; then echo "== ps ==" ps uewww -p $IN_PID echo "== lsof ==" lsof -p $IN_PID else echo "error: inaccessible process -- $IN_PID" > /dev/stderr fi lnav-0.7.0/src/extension-functions.c000664 000765 000024 00000143025 12211635053 017710 0ustar00stackstaff000000 000000 /* This library will provide common mathematical and string functions in SQL queries using the operating system libraries or provided definitions. It includes the following functions: Math: acos, asin, atan, atn2, atan2, acosh, asinh, atanh, difference, degrees, radians, cos, sin, tan, cot, cosh, sinh, tanh, coth, exp, log, log10, power, sign, sqrt, square, ceil, floor, pi. String: replicate, charindex, leftstr, rightstr, ltrim, rtrim, trim, replace, reverse, proper, padl, padr, padc, strfilter. Aggregate: stdev, variance, mode, median, lower_quartile, upper_quartile. The string functions ltrim, rtrim, trim, replace are included in recent versions of SQLite and so by default do not build. Compilation instructions: Compile this C source file into a dynamic library as follows: * Linux: gcc -fPIC -lm -shared extension-functions.c -o libsqlitefunctions.so * Mac OS X: gcc -fno-common -dynamiclib extension-functions.c -o libsqlitefunctions.dylib (You may need to add flags -I /opt/local/include/ -L/opt/local/lib -lsqlite3 if your sqlite3 is installed from Mac ports, or -I /sw/include/ -L/sw/lib -lsqlite3 if installed with Fink.) * Windows: 1. Install MinGW (http://www.mingw.org/) and you will get the gcc (gnu compiler collection) 2. add the path to your path variable (isn't done during the installation!) 3. compile: gcc -shared -I "path" -o libsqlitefunctions.so extension-functions.c (path = path of sqlite3ext.h; i.e. C:\programs\sqlite) Usage instructions for applications calling the sqlite3 API functions: In your application, call sqlite3_enable_load_extension(db,1) to allow loading external libraries. Then load the library libsqlitefunctions using sqlite3_load_extension; the third argument should be 0. See http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. Select statements may now use these functions, as in SELECT cos(radians(inclination)) FROM satsum WHERE satnum = 25544; Usage instructions for the sqlite3 program: If the program is built so that loading extensions is permitted, the following will work: sqlite> SELECT load_extension('./libsqlitefunctions.so'); sqlite> select cos(radians(45)); 0.707106781186548 Note: Loading extensions is by default prohibited as a security measure; see "Security Considerations" in http://www.sqlite.org/cvstrac/wiki?p=LoadableExtensions. If the sqlite3 program and library are built this way, you cannot use these functions from the program, you must write your own program using the sqlite3 API, and call sqlite3_enable_load_extension as described above, or else rebuilt the sqlite3 program to allow loadable extensions. Alterations: The instructions are for Linux, Mac OS X, and Windows; users of other OSes may need to modify this procedure. In particular, if your math library lacks one or more of the needed trig or log functions, comment out the appropriate HAVE_ #define at the top of file. If you do not wish to make a loadable module, comment out the define for COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE. If you are using a version of SQLite without the trim functions and replace, comment out the HAVE_TRIM #define. Liam Healy History: 2010-01-06 Correct check for argc in squareFunc, and add Windows compilation instructions. 2009-06-24 Correct check for argc in properFunc. 2008-09-14 Add check that memory was actually allocated after sqlite3_malloc or sqlite3StrDup, call sqlite3_result_error_nomem if not. Thanks to Robert Simpson. 2008-06-13 Change to instructions to indicate use of the math library and that program might work. 2007-10-01 Minor clarification to instructions. 2007-09-29 Compilation as loadable module is optional with COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE. 2007-09-28 Use sqlite3_extension_init and macros SQLITE_EXTENSION_INIT1, SQLITE_EXTENSION_INIT2, so that it works with sqlite3_load_extension. Thanks to Eric Higashino and Joe Wilson. New instructions for Mac compilation. 2007-09-17 With help from Joe Wilson and Nuno Luca, made use of external interfaces so that compilation is no longer dependent on SQLite source code. Merged source, header, and README into a single file. Added casts so that Mac will compile without warnings (unsigned and signed char). 2007-09-05 Included some definitions from sqlite 3.3.13 so that this will continue to work in newer versions of sqlite. Completed description of functions available. 2007-03-27 Revised description. 2007-03-23 Small cleanup and a bug fix on the code. This was mainly letting errno flag errors encountered in the math library and checking the result, rather than pre-checking. This fixes a bug in power that would cause an error if any non-positive number was raised to any power. 2007-02-07 posted by Mikey C to sqlite mailing list. Original code 2006 June 05 by relicoder. */ //#include "config.h" // #define COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE 1 #define HAVE_ACOSH 1 #define HAVE_ASINH 1 #define HAVE_ATANH 1 #define HAVE_SINH 1 #define HAVE_COSH 1 #define HAVE_TANH 1 #define HAVE_LOG10 1 #define HAVE_ISBLANK 1 #define SQLITE_SOUNDEX 1 #define HAVE_TRIM 1 /* LMH 2007-03-25 if sqlite has trim functions */ #ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #else #include "sqlite3.h" #endif #include /* relicoder */ #include #include #include #include /* LMH 2007-03-25 */ #include #include #ifndef _MAP_H_ #define _MAP_H_ #include #include #include "sqlite-extension-func.h" /* ** Simple binary tree implementation to use in median, mode and quartile calculations ** Tree is not necessarily balanced. That would require something like red&black trees of AVL */ typedef int(*cmp_func)(const void *, const void *); typedef void(*map_iterator)(void*, int64_t, void*); typedef struct node{ struct node *l; struct node *r; void* data; int64_t count; } node; typedef struct map{ node *base; cmp_func cmp; short free; } map; /* ** creates a map given a comparison function */ map map_make(cmp_func cmp); /* ** inserts the element e into map m */ void map_insert(map *m, void *e); /* ** executes function iter over all elements in the map, in key increasing order */ void map_iterate(map *m, map_iterator iter, void* p); /* ** frees all memory used by a map */ void map_destroy(map *m); /* ** compares 2 integers ** to use with map_make */ int int_cmp(const void *a, const void *b); /* ** compares 2 doubles ** to use with map_make */ int double_cmp(const void *a, const void *b); #endif /* _MAP_H_ */ typedef uint8_t u8; typedef uint16_t u16; typedef int64_t i64; static char *sqlite3StrDup( const char *z ) { char *res = sqlite3_malloc( strlen(z)+1 ); return strcpy( res, z ); } /* ** These are copied verbatim from fun.c so as to not have the names exported */ /* LMH from sqlite3 3.3.13 */ /* ** This table maps from the first byte of a UTF-8 character to the number ** of trailing bytes expected. A value '4' indicates that the table key ** is not a legal first byte for a UTF-8 character. */ static const u8 xtra_utf8_bytes[256] = { /* 0xxxxxxx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10wwwwww */ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 110yyyyy */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1110zzzz */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 11110yyy */ 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, }; /* ** This table maps from the number of trailing bytes in a UTF-8 character ** to an integer constant that is effectively calculated for each character ** read by a naive implementation of a UTF-8 character reader. The code ** in the READ_UTF8 macro explains things best. */ static const int xtra_utf8_bits[] = { 0, 12416, /* (0xC0 << 6) + (0x80) */ 925824, /* (0xE0 << 12) + (0x80 << 6) + (0x80) */ 63447168 /* (0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80 */ }; /* ** If a UTF-8 character contains N bytes extra bytes (N bytes follow ** the initial byte so that the total character length is N+1) then ** masking the character with utf8_mask[N] must produce a non-zero ** result. Otherwise, we have an (illegal) overlong encoding. */ static const int utf_mask[] = { 0x00000000, 0xffffff80, 0xfffff800, 0xffff0000, }; /* LMH salvaged from sqlite3 3.3.13 source code src/utf.c */ #define READ_UTF8(zIn, c) { \ int xtra; \ c = *(zIn)++; \ xtra = xtra_utf8_bytes[c]; \ switch( xtra ){ \ case 4: c = (int)0xFFFD; break; \ case 3: c = (c<<6) + *(zIn)++; \ case 2: c = (c<<6) + *(zIn)++; \ case 1: c = (c<<6) + *(zIn)++; \ c -= xtra_utf8_bits[xtra]; \ if( (utf_mask[xtra]&c)==0 \ || (c&0xFFFFF800)==0xD800 \ || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ } \ } static int sqlite3ReadUtf8(const unsigned char *z){ int c; READ_UTF8(z, c); return c; } #define SKIP_UTF8(zIn) { \ zIn += (xtra_utf8_bytes[*(u8 *)zIn] + 1); \ } /* ** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, ** return the number of unicode characters in pZ up to (but not including) ** the first 0x00 byte. If nByte is not less than zero, return the ** number of unicode characters in the first nByte of pZ (or up to ** the first 0x00, whichever comes first). */ static int sqlite3Utf8CharLen(const char *z, int nByte){ int r = 0; const char *zTerm; if( nByte>=0 ){ zTerm = &z[nByte]; }else{ zTerm = (const char *)(-1); } assert( z<=zTerm ); while( *z!=0 && z 0) ? 1: ( iVal < 0 ) ? -1: 0; sqlite3_result_int64(context, iVal); break; } case SQLITE_NULL: { sqlite3_result_null(context); break; } default: { /* 2nd change below. Line for abs was: if( rVal<0 ) rVal = rVal * -1.0; */ rVal = sqlite3_value_double(argv[0]); rVal = ( rVal > 0) ? 1: ( rVal < 0 ) ? -1: 0; sqlite3_result_double(context, rVal); break; } } } /* ** smallest integer value not less than argument */ static void ceilFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ double rVal=0.0; assert( argc==1 ); switch( sqlite3_value_type(argv[0]) ){ case SQLITE_INTEGER: { i64 iVal = sqlite3_value_int64(argv[0]); sqlite3_result_int64(context, iVal); break; } case SQLITE_NULL: { sqlite3_result_null(context); break; } default: { rVal = sqlite3_value_double(argv[0]); sqlite3_result_int64(context, (i64) ceil(rVal)); break; } } } /* ** largest integer value not greater than argument */ static void floorFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ double rVal=0.0; assert( argc==1 ); switch( sqlite3_value_type(argv[0]) ){ case SQLITE_INTEGER: { i64 iVal = sqlite3_value_int64(argv[0]); sqlite3_result_int64(context, iVal); break; } case SQLITE_NULL: { sqlite3_result_null(context); break; } default: { rVal = sqlite3_value_double(argv[0]); sqlite3_result_int64(context, (i64) floor(rVal)); break; } } } /* ** Given a string (s) in the first argument and an integer (n) in the second returns the ** string that constains s contatenated n times */ static void replicateFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ unsigned char *z; /* input string */ unsigned char *zo; /* result string */ i64 iCount; /* times to repeat */ i64 nLen; /* length of the input string (no multibyte considerations) */ i64 nTLen; /* length of the result string (no multibyte considerations) */ i64 i=0; if( argc!=2 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; iCount = sqlite3_value_int64(argv[1]); if( iCount<0 ){ sqlite3_result_error(context, "domain error", -1); }else{ nLen = sqlite3_value_bytes(argv[0]); nTLen = nLen*iCount; z=sqlite3_malloc(nTLen+1); zo=sqlite3_malloc(nLen+1); if (!z || !zo){ sqlite3_result_error_nomem(context); if (z) sqlite3_free(z); if (zo) sqlite3_free(zo); return; } strcpy((char*)zo, (char*)sqlite3_value_text(argv[0])); for(i=0; i=n it's a NOP ** padl(NULL) = NULL */ static void padlFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ i64 ilen; /* length to pad to */ i64 zl; /* length of the input string (UTF-8 chars) */ int i = 0; const char *zi; /* input string */ char *zo; /* output string */ char *zt; assert( argc==2 ); if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ sqlite3_result_null(context); }else{ zi = (char *)sqlite3_value_text(argv[0]); ilen = sqlite3_value_int64(argv[1]); /* check domain */ if(ilen<0){ sqlite3_result_error(context, "domain error", -1); return; } zl = sqlite3Utf8CharLen(zi, -1); if( zl>=ilen ){ /* string is longer than the requested pad length, return the same string (dup it) */ zo = sqlite3StrDup(zi); if (!zo){ sqlite3_result_error_nomem(context); return; } sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); }else{ zo = sqlite3_malloc(strlen(zi)+ilen-zl+1); if (!zo){ sqlite3_result_error_nomem(context); return; } zt = zo; for(i=1; i+zl<=ilen; ++i){ *(zt++)=' '; } /* no need to take UTF-8 into consideration here */ strcpy(zt,zi); } sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); sqlite3_free(zo); } } /* ** given an input string (s) and an integer (n) appends spaces at the end of s ** until it has a length of n characters. ** When s has a length >=n it's a NOP ** padl(NULL) = NULL */ static void padrFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ i64 ilen; /* length to pad to */ i64 zl; /* length of the input string (UTF-8 chars) */ i64 zll; /* length of the input string (bytes) */ int i = 0; const char *zi; /* input string */ char *zo; /* output string */ char *zt; assert( argc==2 ); if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ sqlite3_result_null(context); }else{ zi = (char *)sqlite3_value_text(argv[0]); ilen = sqlite3_value_int64(argv[1]); /* check domain */ if(ilen<0){ sqlite3_result_error(context, "domain error", -1); return; } zl = sqlite3Utf8CharLen(zi, -1); if( zl>=ilen ){ /* string is longer than the requested pad length, return the same string (dup it) */ zo = sqlite3StrDup(zi); if (!zo){ sqlite3_result_error_nomem(context); return; } sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); }else{ zll = strlen(zi); zo = sqlite3_malloc(zll+ilen-zl+1); if (!zo){ sqlite3_result_error_nomem(context); return; } zt = strcpy(zo,zi)+zll; for(i=1; i+zl<=ilen; ++i){ *(zt++) = ' '; } *zt = '\0'; } sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); sqlite3_free(zo); } } /* ** given an input string (s) and an integer (n) appends spaces at the end of s ** and adds spaces at the begining of s until it has a length of n characters. ** Tries to add has many characters at the left as at the right. ** When s has a length >=n it's a NOP ** padl(NULL) = NULL */ static void padcFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ i64 ilen; /* length to pad to */ i64 zl; /* length of the input string (UTF-8 chars) */ i64 zll; /* length of the input string (bytes) */ int i = 0; const char *zi; /* input string */ char *zo; /* output string */ char *zt; assert( argc==2 ); if( sqlite3_value_type(argv[0]) == SQLITE_NULL ){ sqlite3_result_null(context); }else{ zi = (char *)sqlite3_value_text(argv[0]); ilen = sqlite3_value_int64(argv[1]); /* check domain */ if(ilen<0){ sqlite3_result_error(context, "domain error", -1); return; } zl = sqlite3Utf8CharLen(zi, -1); if( zl>=ilen ){ /* string is longer than the requested pad length, return the same string (dup it) */ zo = sqlite3StrDup(zi); if (!zo){ sqlite3_result_error_nomem(context); return; } sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); }else{ zll = strlen(zi); zo = sqlite3_malloc(zll+ilen-zl+1); if (!zo){ sqlite3_result_error_nomem(context); return; } zt = zo; for(i=1; 2*i+zl<=ilen; ++i){ *(zt++) = ' '; } strcpy(zt, zi); zt+=zll; for(; i+zl<=ilen; ++i){ *(zt++) = ' '; } *zt = '\0'; } sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); sqlite3_free(zo); } } /* ** given 2 string (s1,s2) returns the string s1 with the characters NOT in s2 removed ** assumes strings are UTF-8 encoded */ static void strfilterFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *zi1; /* first parameter string (searched string) */ const char *zi2; /* second parameter string (vcontains valid characters) */ const char *z1; const char *z21; const char *z22; char *zo; /* output string */ char *zot; int c1 = 0; int c2 = 0; assert( argc==2 ); if( sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL ){ sqlite3_result_null(context); }else{ zi1 = (char *)sqlite3_value_text(argv[0]); zi2 = (char *)sqlite3_value_text(argv[1]); /* ** maybe I could allocate less, but that would imply 2 passes, rather waste ** (possibly) some memory */ zo = sqlite3_malloc(strlen(zi1)+1); if (!zo){ sqlite3_result_error_nomem(context); return; } zot = zo; z1 = zi1; while( (c1=sqliteCharVal((unsigned char *)z1))!=0 ){ z21=zi2; while( (c2=sqliteCharVal((unsigned char *)z21))!=0 && c2!=c1 ){ sqliteNextChar(z21); } if( c2!=0){ z22=z21; sqliteNextChar(z22); strncpy(zot, z21, z22-z21); zot+=z22-z21; } sqliteNextChar(z1); } *zot = '\0'; sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); sqlite3_free(zo); } } /* ** Given a string z1, retutns the (0 based) index of it's first occurence ** in z2 after the first s characters. ** Returns -1 when there isn't a match. ** updates p to point to the character where the match occured. ** This is an auxiliary function. */ static int _substr(const char* z1, const char* z2, int s, const char** p){ int c = 0; int rVal=-1; const char* zt1; const char* zt2; int c1,c2; if( '\0'==*z1 ){ return -1; } while( (sqliteCharVal((unsigned char *)z2) != 0) && (c++)=0 ? rVal+s : rVal; } /* ** given 2 input strings (s1,s2) and an integer (n) searches from the nth character ** for the string s1. Returns the position where the match occured. ** Characters are counted from 1. ** 0 is returned when no match occurs. */ static void charindexFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ const u8 *z1; /* s1 string */ u8 *z2; /* s2 string */ int s=0; int rVal=0; assert( argc==3 ||argc==2); if( SQLITE_NULL==sqlite3_value_type(argv[0]) || SQLITE_NULL==sqlite3_value_type(argv[1])){ sqlite3_result_null(context); return; } z1 = sqlite3_value_text(argv[0]); if( z1==0 ) return; z2 = (u8*) sqlite3_value_text(argv[1]); if(argc==3){ s = sqlite3_value_int(argv[2])-1; if(s<0){ s=0; } }else{ s = 0; } rVal = _substr((char *)z1,(char *)z2,s,NULL); sqlite3_result_int(context, rVal+1); } /* ** given a string (s) and an integer (n) returns the n leftmost (UTF-8) characters ** if the string has a length<=n or is NULL this function is NOP */ static void leftFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ int c=0; int cc=0; int l=0; const unsigned char *z; /* input string */ const unsigned char *zt; unsigned char *rz; /* output string */ assert( argc==2); if( SQLITE_NULL==sqlite3_value_type(argv[0]) || SQLITE_NULL==sqlite3_value_type(argv[1])){ sqlite3_result_null(context); return; } z = sqlite3_value_text(argv[0]); l = sqlite3_value_int(argv[1]); zt = z; while( sqliteCharVal(zt) && c++ 0 ){ sqliteNextChar(zt); } rz = sqlite3_malloc(ze-zt+1); if (!rz){ sqlite3_result_error_nomem(context); return; } strcpy((char*) rz, (char*) (zt)); sqlite3_result_text(context, (char*)rz, -1, SQLITE_TRANSIENT); sqlite3_free(rz); } #ifndef HAVE_TRIM /* ** removes the whitespaces at the begining of a string. */ const char* ltrim(const char* s){ while( *s==' ' ) ++s; return s; } /* ** removes the whitespaces at the end of a string. ** !mutates the input string! */ void rtrim(char* s){ char* ss = s+strlen(s)-1; while( ss>=s && *ss==' ' ) --ss; *(ss+1)='\0'; } /* ** Removes the whitespace at the begining of a string */ static void ltrimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *z; assert( argc==1); if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ sqlite3_result_null(context); return; } z = sqlite3_value_text(argv[0]); sqlite3_result_text(context, ltrim(z), -1, SQLITE_TRANSIENT); } /* ** Removes the whitespace at the end of a string */ static void rtrimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *z; char *rz; /* try not to change data in argv */ assert( argc==1); if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ sqlite3_result_null(context); return; } z = sqlite3_value_text(argv[0]); rz = sqlite3StrDup(z); rtrim(rz); sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT); sqlite3_free(rz); } /* ** Removes the whitespace at the begining and end of a string */ static void trimFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *z; char *rz; /* try not to change data in argv */ assert( argc==1); if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ sqlite3_result_null(context); return; } z = sqlite3_value_text(argv[0]); rz = sqlite3StrDup(z); rtrim(rz); sqlite3_result_text(context, ltrim(rz), -1, SQLITE_TRANSIENT); sqlite3_free(rz); } #endif /* ** given a pointer to a string s1, the length of that string (l1), a new string (s2) ** and it's length (l2) appends s2 to s1. ** All lengths in bytes. ** This is just an auxiliary function */ // static void _append(char **s1, int l1, const char *s2, int l2){ // *s1 = realloc(*s1, (l1+l2+1)*sizeof(char)); // strncpy((*s1)+l1, s2, l2); // *(*(s1)+l1+l2) = '\0'; // } #ifndef HAVE_TRIM /* ** given strings s, s1 and s2 replaces occurrences of s1 in s by s2 */ static void replaceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *z1; /* string s (first parameter) */ const char *z2; /* string s1 (second parameter) string to look for */ const char *z3; /* string s2 (third parameter) string to replace occurrences of s1 with */ int lz1; int lz2; int lz3; int lzo=0; char *zo=0; int ret=0; const char *zt1; const char *zt2; assert( 3==argc ); if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ sqlite3_result_null(context); return; } z1 = sqlite3_value_text(argv[0]); z2 = sqlite3_value_text(argv[1]); z3 = sqlite3_value_text(argv[2]); /* handle possible null values */ if( 0==z2 ){ z2=""; } if( 0==z3 ){ z3=""; } lz1 = strlen(z1); lz2 = strlen(z2); lz3 = strlen(z3); #if 0 /* special case when z2 is empty (or null) nothing will be changed */ if( 0==lz2 ){ sqlite3_result_text(context, z1, -1, SQLITE_TRANSIENT); return; } #endif zt1=z1; zt2=z1; while(1){ ret=_substr(z2,zt1 , 0, &zt2); if( ret<0 ) break; _append(&zo, lzo, zt1, zt2-zt1); lzo+=zt2-zt1; _append(&zo, lzo, z3, lz3); lzo+=lz3; zt1=zt2+lz2; } _append(&zo, lzo, zt1, lz1-(zt1-z1)); sqlite3_result_text(context, zo, -1, SQLITE_TRANSIENT); sqlite3_free(zo); } #endif /* ** given a string returns the same string but with the characters in reverse order */ static void reverseFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *z; const char *zt; char *rz; char *rzt; int l = 0; int i = 0; assert( 1==argc ); if( SQLITE_NULL==sqlite3_value_type(argv[0]) ){ sqlite3_result_null(context); return; } z = (char *)sqlite3_value_text(argv[0]); l = strlen(z); rz = sqlite3_malloc(l+1); if (!rz){ sqlite3_result_error_nomem(context); return; } rzt = rz+l; *(rzt--) = '\0'; zt=z; while( sqliteCharVal((unsigned char *)zt)!=0 ){ z=zt; sqliteNextChar(zt); for(i=1; zt-i>=z; ++i){ *(rzt--)=*(zt-i); } } sqlite3_result_text(context, rz, -1, SQLITE_TRANSIENT); sqlite3_free(rz); } /* ** An instance of the following structure holds the context of a ** stdev() or variance() aggregate computation. ** implementaion of http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Algorithm_II ** less prone to rounding errors */ typedef struct StdevCtx StdevCtx; struct StdevCtx { double rM; double rS; i64 cnt; /* number of elements */ }; /* ** An instance of the following structure holds the context of a ** mode() or median() aggregate computation. ** Depends on structures defined in map.c (see map & map) ** These aggregate functions only work for integers and floats although ** they could be made to work for strings. This is usually considered meaningless. ** Only usuall order (for median), no use of collation functions (would this even make sense?) */ typedef struct ModeCtx ModeCtx; struct ModeCtx { i64 riM; /* integer value found so far */ double rdM; /* double value found so far */ i64 cnt; /* number of elements so far */ double pcnt; /* number of elements smaller than a percentile */ i64 mcnt; /* maximum number of occurrences (for mode) */ i64 mn; /* number of occurrences (for mode and percentiles) */ i64 is_double; /* whether the computation is being done for doubles (>0) or integers (=0) */ map* m; /* map structure used for the computation */ int done; /* whether the answer has been found */ }; /* ** called for each value received during a calculation of stdev or variance */ static void varianceStep(sqlite3_context *context, int argc, sqlite3_value **argv){ StdevCtx *p; double delta; double x; assert( argc==1 ); p = sqlite3_aggregate_context(context, sizeof(*p)); /* only consider non-null values */ if( SQLITE_NULL != sqlite3_value_numeric_type(argv[0]) ){ p->cnt++; x = sqlite3_value_double(argv[0]); delta = (x-p->rM); p->rM += delta/p->cnt; p->rS += delta*(x-p->rM); } } /* ** called for each value received during a calculation of mode of median */ static void modeStep(sqlite3_context *context, int argc, sqlite3_value **argv){ ModeCtx *p; i64 xi=0; double xd=0.0; i64 *iptr; double *dptr; int type; assert( argc==1 ); type = sqlite3_value_numeric_type(argv[0]); if( type == SQLITE_NULL) return; p = sqlite3_aggregate_context(context, sizeof(*p)); if( 0==(p->m) ){ p->m = calloc(1, sizeof(map)); if( type==SQLITE_INTEGER ){ /* map will be used for integers */ *(p->m) = map_make(int_cmp); p->is_double = 0; }else{ p->is_double = 1; /* map will be used for doubles */ *(p->m) = map_make(double_cmp); } } ++(p->cnt); if( 0==p->is_double ){ xi = sqlite3_value_int64(argv[0]); iptr = (i64*)calloc(1,sizeof(i64)); *iptr = xi; map_insert(p->m, iptr); }else{ xd = sqlite3_value_double(argv[0]); dptr = (double*)calloc(1,sizeof(double)); *dptr = xd; map_insert(p->m, dptr); } } /* ** Auxiliary function that iterates all elements in a map and finds the mode ** (most frequent value) */ static void modeIterate(void* e, i64 c, void* pp){ i64 ei; double ed; ModeCtx *p = (ModeCtx*)pp; if( 0==p->is_double ){ ei = *(int*)(e); if( p->mcnt==c ){ ++p->mn; }else if( p->mcntriM = ei; p->mcnt = c; p->mn=1; } }else{ ed = *(double*)(e); if( p->mcnt==c ){ ++p->mn; }else if(p->mcntrdM = ed; p->mcnt = c; p->mn=1; } } } /* ** Auxiliary function that iterates all elements in a map and finds the median ** (the value such that the number of elements smaller is equal the the number of ** elements larger) */ static void medianIterate(void* e, i64 c, void* pp){ i64 ei; double ed; double iL; double iR; int il; int ir; ModeCtx *p = (ModeCtx*)pp; if(p->done>0) return; iL = p->pcnt; iR = p->cnt - p->pcnt; il = p->mcnt + c; ir = p->cnt - p->mcnt; if( il >= iL ){ if( ir >= iR ){ ++p->mn; if( 0==p->is_double ){ ei = *(int*)(e); p->riM += ei; }else{ ed = *(double*)(e); p->rdM += ed; } }else{ p->done=1; } } p->mcnt+=c; } /* ** Returns the mode value */ static void modeFinalize(sqlite3_context *context){ ModeCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->m ){ map_iterate(p->m, modeIterate, p); map_destroy(p->m); free(p->m); if( 1==p->mn ){ if( 0==p->is_double ) sqlite3_result_int64(context, p->riM); else sqlite3_result_double(context, p->rdM); } } } /* ** auxiliary function for percentiles */ static void _medianFinalize(sqlite3_context *context){ ModeCtx *p; p = (ModeCtx*) sqlite3_aggregate_context(context, 0); if( p && p->m ){ p->done=0; map_iterate(p->m, medianIterate, p); map_destroy(p->m); free(p->m); if( 0==p->is_double ) if( 1==p->mn ) sqlite3_result_int64(context, p->riM); else sqlite3_result_double(context, p->riM*1.0/p->mn); else sqlite3_result_double(context, p->rdM/p->mn); } } /* ** Returns the median value */ static void medianFinalize(sqlite3_context *context){ ModeCtx *p; p = (ModeCtx*) sqlite3_aggregate_context(context, 0); if( p!=0 ){ p->pcnt = (p->cnt)/2.0; _medianFinalize(context); } } /* ** Returns the lower_quartile value */ static void lower_quartileFinalize(sqlite3_context *context){ ModeCtx *p; p = (ModeCtx*) sqlite3_aggregate_context(context, 0); if( p!=0 ){ p->pcnt = (p->cnt)/4.0; _medianFinalize(context); } } /* ** Returns the upper_quartile value */ static void upper_quartileFinalize(sqlite3_context *context){ ModeCtx *p; p = (ModeCtx*) sqlite3_aggregate_context(context, 0); if( p!=0 ){ p->pcnt = (p->cnt)*3/4.0; _medianFinalize(context); } } /* ** Returns the stdev value */ static void stdevFinalize(sqlite3_context *context){ StdevCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>1 ){ sqlite3_result_double(context, sqrt(p->rS/(p->cnt-1))); }else{ sqlite3_result_double(context, 0.0); } } /* ** Returns the variance value */ static void varianceFinalize(sqlite3_context *context){ StdevCtx *p; p = sqlite3_aggregate_context(context, 0); if( p && p->cnt>1 ){ sqlite3_result_double(context, p->rS/(p->cnt-1)); }else{ sqlite3_result_double(context, 0.0); } } #ifdef SQLITE_SOUNDEX /* relicoder factored code */ /* ** Calculates the soundex value of a string */ static void soundex(const u8 *zIn, char *zResult){ int i, j; static const unsigned char iCode[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, }; for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} if( zIn[i] ){ zResult[0] = toupper(zIn[i]); for(j=1; j<4 && zIn[i]; i++){ int code = iCode[zIn[i]&0x7f]; if( code>0 ){ zResult[j++] = code + '0'; } } while( j<4 ){ zResult[j++] = '0'; } zResult[j] = 0; }else{ strcpy(zResult, "?000"); } } /* ** computes the number of different characters between the soundex value fo 2 strings */ static void differenceFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ char zResult1[8]; char zResult2[8]; char *zR1 = zResult1; char *zR2 = zResult2; int rVal = 0; int i = 0; const u8 *zIn1; const u8 *zIn2; assert( argc==2 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL || sqlite3_value_type(argv[1])==SQLITE_NULL ){ sqlite3_result_null(context); return; } zIn1 = (u8*)sqlite3_value_text(argv[0]); zIn2 = (u8*)sqlite3_value_text(argv[1]); soundex(zIn1, zR1); soundex(zIn2, zR2); for(i=0; i<4; ++i){ if( sqliteCharVal((unsigned char *)zR1)==sqliteCharVal((unsigned char *)zR2) ) ++rVal; sqliteNextChar(zR1); sqliteNextChar(zR2); } sqlite3_result_int(context, rVal); } #endif /* ** This function registered all of the above C functions as SQL ** functions. This should be the only routine in this file with ** external linkage. */ int common_extension_functions(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs) { static const struct FuncDef aFuncs[] = { /* math.h */ { "acos", 1, 0, SQLITE_UTF8, 0, acosFunc }, { "asin", 1, 0, SQLITE_UTF8, 0, asinFunc }, { "atan", 1, 0, SQLITE_UTF8, 0, atanFunc }, { "atn2", 2, 0, SQLITE_UTF8, 0, atn2Func }, /* XXX alias */ { "atan2", 2, 0, SQLITE_UTF8, 0, atn2Func }, { "acosh", 1, 0, SQLITE_UTF8, 0, acoshFunc }, { "asinh", 1, 0, SQLITE_UTF8, 0, asinhFunc }, { "atanh", 1, 0, SQLITE_UTF8, 0, atanhFunc }, { "difference", 2, 0, SQLITE_UTF8, 0, differenceFunc}, { "degrees", 1, 0, SQLITE_UTF8, 0, rad2degFunc }, { "radians", 1, 0, SQLITE_UTF8, 0, deg2radFunc }, { "cos", 1, 0, SQLITE_UTF8, 0, cosFunc }, { "sin", 1, 0, SQLITE_UTF8, 0, sinFunc }, { "tan", 1, 0, SQLITE_UTF8, 0, tanFunc }, { "cot", 1, 0, SQLITE_UTF8, 0, cotFunc }, { "cosh", 1, 0, SQLITE_UTF8, 0, coshFunc }, { "sinh", 1, 0, SQLITE_UTF8, 0, sinhFunc }, { "tanh", 1, 0, SQLITE_UTF8, 0, tanhFunc }, { "coth", 1, 0, SQLITE_UTF8, 0, cothFunc }, { "exp", 1, 0, SQLITE_UTF8, 0, expFunc }, { "log", 1, 0, SQLITE_UTF8, 0, logFunc }, { "log10", 1, 0, SQLITE_UTF8, 0, log10Func }, { "power", 2, 0, SQLITE_UTF8, 0, powerFunc }, { "sign", 1, 0, SQLITE_UTF8, 0, signFunc }, { "sqrt", 1, 0, SQLITE_UTF8, 0, sqrtFunc }, { "square", 1, 0, SQLITE_UTF8, 0, squareFunc }, { "ceil", 1, 0, SQLITE_UTF8, 0, ceilFunc }, { "floor", 1, 0, SQLITE_UTF8, 0, floorFunc }, { "pi", 0, 0, SQLITE_UTF8, 1, piFunc }, /* string */ { "replicate", 2, 0, SQLITE_UTF8, 0, replicateFunc }, { "charindex", 2, 0, SQLITE_UTF8, 0, charindexFunc }, { "charindex", 3, 0, SQLITE_UTF8, 0, charindexFunc }, { "leftstr", 2, 0, SQLITE_UTF8, 0, leftFunc }, { "rightstr", 2, 0, SQLITE_UTF8, 0, rightFunc }, #ifndef HAVE_TRIM { "ltrim", 1, 0, SQLITE_UTF8, 0, ltrimFunc }, { "rtrim", 1, 0, SQLITE_UTF8, 0, rtrimFunc }, { "trim", 1, 0, SQLITE_UTF8, 0, trimFunc }, { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc }, #endif { "reverse", 1, 0, SQLITE_UTF8, 0, reverseFunc }, { "proper", 1, 0, SQLITE_UTF8, 0, properFunc }, { "padl", 2, 0, SQLITE_UTF8, 0, padlFunc }, { "padr", 2, 0, SQLITE_UTF8, 0, padrFunc }, { "padc", 2, 0, SQLITE_UTF8, 0, padcFunc }, { "strfilter", 2, 0, SQLITE_UTF8, 0, strfilterFunc }, { NULL } }; /* Aggregate functions */ static const struct FuncDefAgg aAggs[] = { { "stdev", 1, 0, 0, varianceStep, stdevFinalize }, { "stddev", 1, 0, 0, varianceStep, stdevFinalize }, { "variance", 1, 0, 0, varianceStep, varianceFinalize }, { "mode", 1, 0, 0, modeStep, modeFinalize }, { "median", 1, 0, 0, modeStep, medianFinalize }, { "lower_quartile", 1, 0, 0, modeStep, lower_quartileFinalize }, { "upper_quartile", 1, 0, 0, modeStep, upper_quartileFinalize }, { NULL } }; *basic_funcs = aFuncs; *agg_funcs = aAggs; return SQLITE_OK; } #ifdef COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE int sqlite3_extension_init( sqlite3 *db, char **pzErrMsg, const sqlite3_api_routines *pApi){ SQLITE_EXTENSION_INIT2(pApi); RegisterExtensionFunctions(db); return 0; } #endif /* COMPILE_SQLITE_EXTENSIONS_AS_LOADABLE_MODULE */ map map_make(cmp_func cmp){ map r; r.cmp=cmp; r.base = 0; r.free = 0; return r; } void* xcalloc(size_t nmemb, size_t size, char* s){ void* ret = calloc(nmemb, size); return ret; } static void xfree(void* p){ free(p); } void node_insert(node** n, cmp_func cmp, void *e){ int c; node* nn; if(*n==0){ nn = (node*)xcalloc(1,sizeof(node), "for node"); nn->data = e; nn->count = 1; *n=nn; }else{ c=cmp((*n)->data,e); if(0==c){ ++((*n)->count); xfree(e); }else if(c>0){ /* put it right here */ node_insert(&((*n)->l), cmp, e); }else{ node_insert(&((*n)->r), cmp, e); } } } void map_insert(map *m, void *e){ node_insert(&(m->base), m->cmp, e); } void node_iterate(node *n, map_iterator iter, void* p){ if(n){ if(n->l) node_iterate(n->l, iter, p); iter(n->data, n->count, p); if(n->r) node_iterate(n->r, iter, p); } } void map_iterate(map *m, map_iterator iter, void* p){ node_iterate(m->base, iter, p); } void node_destroy(node *n){ if(0!=n){ xfree(n->data); if(n->l) node_destroy(n->l); if(n->r) node_destroy(n->r); xfree(n); } } void map_destroy(map *m){ node_destroy(m->base); } int int_cmp(const void *a, const void *b){ int64_t aa = *(int64_t *)(a); int64_t bb = *(int64_t *)(b); /* printf("cmp %d <=> %d\n",aa,bb); */ if(aa==bb) return 0; else if(aa %d\n",aa,bb); */ if(aa==bb) return 0; else if(aa %" PRId64 "\n", ee,c); } lnav-0.7.0/src/format-text-files.hh000644 000765 000024 00000003232 12221553323 017406 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file format-text-files.hh */ #ifndef __format_text_files_hh #define __format_text_files_hh extern "C" { extern const char dump_pid_sh[]; } #endif lnav-0.7.0/src/fs-extension-functions.cc000664 000765 000024 00000012443 12265152265 020470 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file fs-extension-functions.cc */ #include #include #include #include #include #include "sqlite3.h" #include "sqlite-extension-func.h" static void sql_basename(sqlite3_context *context, int argc, sqlite3_value **argv) { const char *path_in; int text_end = -1; if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { sqlite3_result_null(context); return; } path_in = (const char *)sqlite3_value_text(argv[0]); if (path_in[0] == '\0') { sqlite3_result_text(context, ".", 1, SQLITE_STATIC); return; } for (int lpc = strlen(path_in) - 1; lpc >= 0; lpc--) { if (path_in[lpc] == '/' || path_in[lpc] == '\\') { if (text_end != -1) { sqlite3_result_text(context, &path_in[lpc + 1], text_end - lpc - 1, SQLITE_TRANSIENT); return; } } else if (text_end == -1) { text_end = lpc + 1; } } if (text_end == -1) { sqlite3_result_text(context, "/", 1, SQLITE_STATIC); } else { sqlite3_result_text(context, path_in, text_end, SQLITE_TRANSIENT); } } static void sql_dirname(sqlite3_context *context, int argc, sqlite3_value **argv) { const char *path_in; int text_end; if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { sqlite3_result_null(context); return; } path_in = (const char *)sqlite3_value_text(argv[0]); text_end = strlen(path_in) - 1; while (text_end >= 0 && (path_in[text_end] == '/' || path_in[text_end] == '\\')) { text_end -= 1; } while (text_end >= 0) { if (path_in[text_end] == '/' || path_in[text_end] == '\\') { sqlite3_result_text(context, path_in, text_end == 0 ? 1 : text_end, SQLITE_TRANSIENT); return; } text_end -= 1; } if (text_end == -1) { sqlite3_result_text(context, path_in[0] == '/' ? "/" : ".", 1, SQLITE_STATIC); return; } } static void sql_joinpath(sqlite3_context *context, int argc, sqlite3_value **argv) { std::string full_path; int lpc; if (argc == 0) { sqlite3_result_null(context); return; } for (lpc = 0; lpc < argc; lpc++) { if (sqlite3_value_type(argv[lpc]) == SQLITE_NULL) { sqlite3_result_null(context); return; } } for (lpc = 0; lpc < argc; lpc++) { const char *path_in; path_in = (const char *)sqlite3_value_text(argv[lpc]); if (path_in[0] == '/' || path_in[0] == '\\') { full_path.clear(); } if (!full_path.empty() && full_path[full_path.length() - 1] != '/' && full_path[full_path.length() - 1] != '\\') { full_path += "/"; } full_path += path_in; } sqlite3_result_text(context, full_path.c_str(), -1, SQLITE_TRANSIENT); } int fs_extension_functions(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs) { static const struct FuncDef fs_funcs[] = { { "basename", 1, 0, SQLITE_UTF8, 0, sql_basename }, { "dirname", 1, 0, SQLITE_UTF8, 0, sql_dirname }, { "joinpath", -1, 0, SQLITE_UTF8, 0, sql_joinpath }, /* * TODO: add other functions like readlink, normpath, ... */ { NULL } }; *basic_funcs = fs_funcs; *agg_funcs = NULL; return SQLITE_OK; } lnav-0.7.0/src/grapher.hh000664 000765 000024 00000010513 12211635053 015466 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file grapher.hh */ #ifndef _grapher_hh #define _grapher_hh #include "config.h" #include #include #include "grep_proc.hh" #include "hist_source.hh" #include "textview_curses.hh" class grapher : public grep_proc_sink, public hist_source { public: grapher() : gr_highlighter(NULL) { this->set_label_source(&this->gr_label_source); }; grep_line_t at(int row) { return this->gr_lines[row]; }; void set_highlighter(textview_curses::highlighter *hl) { this->gr_highlighter = hl; }; void grep_begin(grep_proc &gp) { this->clear(); this->hs_type2role.clear(); this->gr_lines.clear(); this->gr_x = -1; this->gr_next_field = bucket_type_t(0); }; void grep_match(grep_proc &gp, grep_line_t line, int start, int end) { }; void grep_capture(grep_proc &gp, grep_line_t line, int start, int end, char *capture) { float amount = 1.0; if (this->gr_lines.empty() || this->gr_lines.back() != line) { this->gr_next_field = bucket_type_t(0); this->gr_x += 1; this->gr_lines.push_back(line); } if (this->gr_highlighter != NULL) { if (this->hs_type2role.find(this->gr_next_field) == this->hs_type2role.end()) { this->hs_type2role[this->gr_next_field] = this->gr_highlighter->get_role(this->gr_next_field); } } if (capture != 0) { sscanf(capture, "%f", &amount); } this->add_value(this->gr_x, this->gr_next_field, amount); ++this->gr_next_field; }; void grep_end_batch(grep_proc &gp) { }; void grep_end(grep_proc &gp) { }; private: class label_source : public hist_source::label_source { public: label_source() { }; void hist_label_for_bucket(int bucket_start_value, const hist_source::bucket_t &bucket, std::string &label_out) { hist_source::bucket_t::const_iterator iter; for (iter = bucket.begin(); iter != bucket.end(); iter++) { char buffer[64]; if (iter->second != 0.0) { snprintf(buffer, sizeof(buffer), " %10.2f", iter->second); } else { snprintf(buffer, sizeof(buffer), " %10s", "-"); } label_out += std::string(buffer); } }; }; label_source gr_label_source; textview_curses::highlighter *gr_highlighter; std::vector gr_lines; int gr_x; bucket_type_t gr_next_field; }; #endif lnav-0.7.0/src/grep_highlighter.hh000664 000765 000024 00000004367 12310065262 017362 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __grep_highlighter_hh #define __grep_highlighter_hh #include #include #include "grep_proc.hh" #include "textview_curses.hh" class grep_highlighter { public: grep_highlighter(std::auto_ptr gp, std::string hl_name, textview_curses::highlight_map_t &hl_map) : gh_grep_proc(gp), gh_hl_name(hl_name), gh_hl_map(hl_map) { }; ~grep_highlighter() { this->gh_hl_map.erase(this->gh_hl_map.find(this->gh_hl_name)); }; grep_proc *get_grep_proc() { return this->gh_grep_proc.get(); }; private: std::auto_ptr gh_grep_proc; std::string gh_hl_name; textview_curses::highlight_map_t &gh_hl_map; }; #endif lnav-0.7.0/src/grep_proc.cc000664 000765 000024 00000026431 12314275315 016017 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file grep_proc.cc */ #include "config.h" #include #include #include #include #include #include #include #include #include "lnav_log.hh" #include "grep_proc.hh" #include "time_T.hh" using namespace std; grep_proc::grep_proc(pcre *code, grep_proc_source &gps, int &maxfd, fd_set &readfds) : gp_pcre(code), gp_code(code), gp_source(gps), gp_pipe_offset(0), gp_child(-1), gp_child_started(false), gp_maxfd(maxfd), gp_readfds(readfds), gp_last_line(0), gp_sink(NULL), gp_control(NULL) { require(this->invariant()); } grep_proc::~grep_proc() { this->gp_queue.clear(); this->cleanup(); } void grep_proc::handle_match(int line, string &line_value, int off, int *matches, int count) { int lpc; if (off == 0) { fprintf(stdout, "%d\n", line); } fprintf(stdout, "[%d:%d]\n", matches[0], matches[1]); for (lpc = 1; lpc < count; lpc++) { fprintf(stdout, "(%d:%d)", matches[lpc * 2], matches[lpc * 2 + 1]); fwrite(&(line_value.c_str()[matches[lpc * 2]]), 1, matches[lpc * 2 + 1] - matches[lpc * 2], stdout); fputc('\n', stdout); } } void grep_proc::start(void) { require(this->invariant()); if (this->gp_child_started || this->gp_queue.empty()) { return; } auto_pipe in_pipe(STDIN_FILENO); auto_pipe out_pipe(STDOUT_FILENO); auto_pipe err_pipe(STDERR_FILENO); /* Get ahold of some pipes for stdout and stderr. */ if (out_pipe.open() < 0) { throw error(errno); } if (err_pipe.open() < 0) { throw error(errno); } if ((this->gp_child = fork()) < 0) { throw error(errno); } in_pipe.after_fork(this->gp_child); out_pipe.after_fork(this->gp_child); err_pipe.after_fork(this->gp_child); if (this->gp_child != 0) { fcntl(out_pipe.read_end(), F_SETFL, O_NONBLOCK); fcntl(out_pipe.read_end(), F_SETFD, 1); this->gp_line_buffer.set_fd(out_pipe.read_end()); fcntl(err_pipe.read_end(), F_SETFL, O_NONBLOCK); fcntl(err_pipe.read_end(), F_SETFD, 1); require(this->gp_err_pipe.get() == -1); this->gp_err_pipe = err_pipe.read_end(); this->gp_child_started = true; FD_SET(this->gp_line_buffer.get_fd(), &this->gp_readfds); FD_SET(this->gp_err_pipe, &this->gp_readfds); this->gp_maxfd = std::max(this->gp_maxfd, std::max(this->gp_line_buffer.get_fd(), this->gp_err_pipe.get())); this->gp_queue.clear(); return; } /* In the child... */ /* * Restore the default signal handlers so we don't hang around * forever if there is a problem. */ signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); this->child_init(); this->child_loop(); _exit(0); } void grep_proc::child_loop(void) { char outbuf[BUFSIZ * 2]; string line_value; stdout = fdopen(STDOUT_FILENO, "w"); /* Make sure buffering is on, not sure of the state in the parent. */ if (setvbuf(stdout, outbuf, _IOFBF, BUFSIZ * 2) < 0) { perror("setvbuf"); } line_value.reserve(BUFSIZ * 2); while (!this->gp_queue.empty()) { grep_line_t start_line = this->gp_queue.front().first; grep_line_t stop_line = this->gp_queue.front().second; bool done = false; int line; this->gp_queue.pop_front(); if (start_line == -1) { start_line = this->gp_highest_line; } for (line = start_line; (stop_line == -1 || line < stop_line) && !done; line++) { line_value.clear(); done = !this->gp_source.grep_value_for_line(line, line_value); if (!done) { pcre_context_static<128> pc; pcre_input pi(line_value); while (this->gp_pcre.match(pc, pi)) { pcre_context::iterator pc_iter; pcre_context::capture_t *m; if (pi.pi_offset == 0) { fprintf(stdout, "%d\n", line); } m = pc.all(); fprintf(stdout, "[%d:%d]\n", m->c_begin, m->c_end); for (pc_iter = pc.begin(); pc_iter != pc.end(); pc_iter++) { fprintf(stdout, "(%d:%d)", pc_iter->c_begin, pc_iter->c_end); /* If the capture was conditional, pcre will return a -1 * here. */ if (pc_iter->c_begin >= 0) { fwrite(pi.get_substr_start(pc_iter), 1, pc_iter->length(), stdout); } fputc('\n', stdout); } fprintf(stdout, "/\n"); } } if (((line + 1) % 10000) == 0) { /* Periodically flush the buffer so the parent sees progress */ this->child_batch(); } } fprintf(stdout, "%d\n", line - 1); this->child_term(); } } void grep_proc::cleanup(void) { if (this->gp_child != -1 && this->gp_child != 0) { int status; kill(this->gp_child, SIGTERM); while (waitpid(this->gp_child, &status, 0) < 0 && (errno == EINTR)) { ; } require(!WIFSIGNALED(status) || WTERMSIG(status) != SIGABRT); this->gp_child = -1; this->gp_child_started = false; if (this->gp_sink) { this->gp_sink->grep_end(*this); } } if (this->gp_err_pipe != -1) { FD_CLR(this->gp_err_pipe, &this->gp_readfds); this->gp_err_pipe.reset(); } if (this->gp_line_buffer.get_fd() != -1) { FD_CLR(this->gp_line_buffer.get_fd(), &this->gp_readfds); } this->gp_pipe_offset = 0; this->gp_line_buffer.reset(); ensure(this->invariant()); if (!this->gp_queue.empty()) { this->start(); } } void grep_proc::dispatch_line(char *line) { int start, end, capture_start; require(line != NULL); if (sscanf(line, "%d", this->gp_last_line.out()) == 1) { /* Starting a new line with matches. */ if (this->gp_last_line > this->gp_highest_line) { this->gp_highest_line = this->gp_last_line; } ensure(this->gp_last_line >= 0); } else if (sscanf(line, "[%d:%d]", &start, &end) == 2) { require(start >= 0); require(end >= 0); /* Pass the match offsets to the sink delegate. */ if (this->gp_sink != NULL) { this->gp_sink->grep_match(*this, this->gp_last_line, start, end); } } else if (sscanf(line, "(%d:%d)%n", &start, &end, &capture_start) == 2) { require(start == -1 || start >= 0); require(end >= 0); /* Pass the captured strings to the sink delegate. */ if (this->gp_sink != NULL) { this->gp_sink->grep_capture(*this, this->gp_last_line, start, end, start < 0 ? NULL : &line[capture_start]); } } else if (line[0] == '/') { if (this->gp_sink != NULL) { this->gp_sink->grep_match_end(*this, this->gp_last_line); } } else { log_error("bad line from child -- %s", line); } } void grep_proc::check_fd_set(fd_set &ready_fds) { require(this->invariant()); if (this->gp_err_pipe != -1 && FD_ISSET(this->gp_err_pipe, &ready_fds)) { char buffer[1024 + 1]; int rc; rc = read(this->gp_err_pipe, buffer, sizeof(buffer) - 1); if (rc > 0) { static const char *PREFIX = ": "; buffer[rc] = '\0'; if (strncmp(buffer, PREFIX, strlen(PREFIX)) == 0) { char *lf; if ((lf = strchr(buffer, '\n')) != NULL) { *lf = '\0'; } if (this->gp_control != NULL) { this->gp_control->grep_error(&buffer[strlen(PREFIX)]); } } } else if (rc == 0) { FD_CLR(this->gp_err_pipe, &this->gp_readfds); this->gp_err_pipe.reset(); } } if (this->gp_line_buffer.get_fd() != -1 && FD_ISSET(this->gp_line_buffer.get_fd(), &ready_fds)) { try { static const int MAX_LOOPS = 100; int loop_count = 0; line_value lv; while ((loop_count < MAX_LOOPS) && (this->gp_line_buffer.read_line(this->gp_pipe_offset, lv))) { lv.lv_start[lv.lv_len] = '\0'; this->dispatch_line(lv.lv_start); loop_count += 1; } if (this->gp_sink != NULL) { this->gp_sink->grep_end_batch(*this); } if ((off_t) this->gp_line_buffer.get_file_size() == this->gp_pipe_offset) { this->cleanup(); } } catch (line_buffer::error & e) { this->cleanup(); } } ensure(this->invariant()); } lnav-0.7.0/src/grep_proc.hh000664 000765 000024 00000023617 12306073365 016036 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file grep_proc.hh */ #ifndef __grep_proc_hh #define __grep_proc_hh #include #include #include #ifdef HAVE_PCRE_H #include #elif HAVE_PCRE_PCRE_H #include #endif #include #include #include #include #include "pcrepp.hh" #include "auto_fd.hh" #include "auto_mem.hh" #include "lnav_log.hh" #include "strong_int.hh" #include "line_buffer.hh" /** Strongly-typed integer for matched line numbers. */ STRONG_INT_TYPE(int, grep_line); class grep_proc; /** * Data source for lines to be searched using a grep_proc. */ class grep_proc_source { public: virtual ~grep_proc_source() { }; /** * Get the value for a particular line in the source. * * @param line The line to retrieve. * @param value_out The destination for the line value. */ virtual bool grep_value_for_line(int line, std::string &value_out) = 0; virtual std::string grep_source_name(void) { return ""; }; }; /** * Delegate interface for control messages from the grep_proc. */ class grep_proc_control { public: virtual ~grep_proc_control() { }; /** @param msg The error encountered while attempting the grep. */ virtual void grep_error(std::string msg) { }; }; /** * Sink for matches produced by a grep_proc instance. */ class grep_proc_sink { public: virtual ~grep_proc_sink() { }; /** Called at the start of a new grep run. */ virtual void grep_begin(grep_proc &gp) { }; /** Called periodically between grep_begin and grep_end. */ virtual void grep_end_batch(grep_proc &gp) { }; /** Called at the end of a grep run. */ virtual void grep_end(grep_proc &gp) { }; /** * Called when a match is found on 'line' and between [start, end). * * @param line The line number that matched. * @param start The offset within the line where the match begins. * @param end The offset of the character after the last character in the * match. */ virtual void grep_match(grep_proc &gp, grep_line_t line, int start, int end) = 0; /** * Called for each captured substring in the line. * * @param line The line number that matched. * @param start The offset within the line where the capture begins. * @param end The offset of the character after the last character in the * capture. * @param capture The captured substring itself. */ virtual void grep_capture(grep_proc &gp, grep_line_t line, int start, int end, char *capture) { }; virtual void grep_match_end(grep_proc &gp, grep_line_t line) { }; }; /** * "Grep" that runs in a separate process so it doesn't stall user-interaction. * This class manages the child process and any interactions between the parent * and child. The source data to be matched comes from the grep_proc_source * delegate and the results are sent to the grep_proc_sink delegate in the * parent process. * * Note: The "grep" executable is not actually used, instead we use the pcre(3) * library directly. */ class grep_proc { public: class error : public std::exception { public: error(int err) : e_err(err) { }; int e_err; }; /** * Construct a grep_proc object. You must call the start() method * to fork off the child process and begin processing. * * @param code The pcre code to run over the lines of input. * @param gps The source of the data to match. * @param readfds The file descriptor set for readable fds. */ grep_proc(pcre *code, grep_proc_source &gps, int &maxfd, fd_set &readfds); virtual ~grep_proc(); /** @return The code passed in to the constructor. */ pcre *get_code() { return this->gp_code; }; /** @param gpd The sink to send resuls to. */ void set_sink(grep_proc_sink *gpd) { this->gp_sink = gpd; this->reset(); }; void reset() { if (this->gp_sink != NULL) { this->gp_sink->grep_begin(*this); } }; void invalidate() { this->cleanup(); }; /** @param gpd The sink to send results to. */ void set_control(grep_proc_control *gpc) { this->gp_control = gpc; }; /** @return The sink to send resuls to. */ grep_proc_sink *get_sink() { return this->gp_sink; }; /** * Queue a request to search the input between the given line numbers. * * @param start The line number to start the search at. * @param stop The line number to stop the search at or -1 to read until * the end-of-file. */ void queue_request(grep_line_t start = grep_line_t(0), grep_line_t stop = grep_line_t(-1)) { require(start != -1 || stop == -1); require(stop == -1 || start < stop); this->gp_queue.push_back(std::make_pair(start, stop)); }; /** * Start the search requests that have been queued up with queue_request. */ void start(void); /** * Check the fd_set to see if there is any new data to be processed. * * @param ready_rfds The set of ready-to-read file descriptors. */ void check_fd_set(fd_set &ready_rfds); /** Check the invariants for this object. */ bool invariant(void) { require(this->gp_code != NULL); if (this->gp_child_started) { require(this->gp_child > 0); require(this->gp_line_buffer.get_fd() != -1); require(FD_ISSET(this->gp_line_buffer.get_fd(), &this->gp_readfds)); } else { require(this->gp_pipe_offset == 0); /* require(this->gp_child == -1); XXX doesnt work with static destr */ require(this->gp_line_buffer.get_fd() == -1); } return true; }; protected: /** * Dispatch a line received from the child. */ void dispatch_line(char *line); /** * Free any resources used by the object and make sure the child has been * terminated. */ void cleanup(void); void child_loop(void); virtual void child_init(void) { }; virtual void child_batch(void) { fflush(stdout); }; virtual void child_term(void) { fflush(stdout); }; virtual void handle_match(int line, std::string &line_value, int off, int *matches, int count); pcrepp gp_pcre; pcre * gp_code; /*< The compiled pattern. */ grep_proc_source & gp_source; /*< The data source delegate. */ auto_fd gp_err_pipe; /*< Standard error from the child. */ line_buffer gp_line_buffer; /*< Standard out from the child. */ off_t gp_pipe_offset; pid_t gp_child; /*< * The child's pid or zero in the * child. */ bool gp_child_started; /*< True if the child was start()'d. */ int & gp_maxfd; fd_set & gp_readfds; /*< * Pointer to the read fd_set so we can * clear our file descriptors later. */ /** The queue of search requests. */ std::deque > gp_queue; grep_line_t gp_last_line; /*< * The last line number received from * the child. For multiple matches, * the line number is only sent once. */ grep_line_t gp_highest_line; /*< The highest numbered line processed * by the grep child process. This * value is used when the start line * for a queued request is -1. */ grep_proc_sink * gp_sink; /*< The sink delegate. */ grep_proc_control *gp_control; /*< The control delegate. */ }; #endif lnav-0.7.0/src/help.hh000664 000765 000024 00000003405 12211635053 014770 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file help.hh */ #ifndef __help_hh #define __help_hh extern "C" { /** * The help message text. The value for this comes from the "help.txt" file, * which gets linked into the executable by the Makefile. */ extern const char help_txt[]; } #endif lnav-0.7.0/src/help.txt000664 000765 000024 00000065161 12313207121 015211 0ustar00stackstaff000000 000000 lnav - A fancy log file viewer DESCRIPTION ----------- The log file navigator, lnav, is an enhanced log file viewer that takes advantage of any semantic information that can be gleaned from the files being viewed, such as timestamps and log levels. Using this extra semantic information, lnav can do things like interleaving messages from different files, generate histograms of messages over time, and providing hotkeys for navigating through the file. It is hoped that these features will allow the user to quickly and efficiently zero in on problems. OPTIONS ------- Lnav takes a list of files to view and/or you can use the flag arguments to load well-known log files, such as the syslog or apache log files. The flag arguments are: -s Load the most recent syslog messages file. (Default) -a Load all of the most recent log file types. -r Load older rotated log files as well. When using the flag arguments, lnav will look for the files relative to the current directory and its parent directories. In other words, if you are working within a directory that has the well-known log files, those will be preferred over any others. Any files given on the command-line are scanned to determine their log file format and to create an index for each line in the file. You do not have to manually specify the log file format. The currently supported formats are: syslog, apache, strace, tcsh history, and generic log files with timestamps. Lnav will also display data piped in on the standard input. The following options are available when doing so: -t Prepend timestamps to the lines of data being read in on the standard input. -w file Write the contents of the standard input to this file. To automatically execute queries or lnav commands after the files have been loaded, you can use the following options: -c cmd A command, query, or file to execute. The first character determines the type of operation: a colon is used for the built-in commands; a semi-colon for SQL queries; and a pipe symbol (|) for executing a file containing other commands. For example, to open the file "foo.log" and go to the tenth line in the file, you can do: lnav -c ':goto 10' foo.log This option can be given multiple times to execute multiple operations in sequence. -f file A file that contains commands, queries, or files to execute. This option is a shortcut for "-c '|file'". To execute commands/queries without the opening the interactive text UI, you can pass the '-n' option. This combination of options allows you to write scripts for processing logs with lnav. For example, to get a list of IP addresses that dhclient has bound to in CSV format: #! /usr/bin/lnav -nf # Usage: dhcp_ip.lnav /var/log/messages # Only include lines that look like: # Apr 29 00:31:56 example-centos5 dhclient: bound to 10.1.10.103 -- renewal in 9938 seconds. :filter-in dhclient: bound to # The log message parser will extract the IP address as col_0, so we # select that and alias it to "dhcp_ip". ;select distinct col_0 as dhcp_ip from logline; # Finally, write the results of the query to stdout. :write-csv-to - DISPLAY ------- The main part of the display shows the log lines from the files interleaved based on time-of-day. New lines are automatically loaded as they are appended to the files and, if you are viewing the bottom of the files, lnav will scroll down to display the new lines, much like 'tail -f'. On color displays, the lines will be highlighted as follows: * Errors will be colored in red; * warnings will be yellow; * boundaries between days will be underlined; and * various color highlights will be applied to: IP addresses, SQL keywords, XML tags, file and line numbers in Java backtraces, and quoted strings. To give you an idea of where you are in the file spatially, the right side of the display has a proportionally sized 'scroll bar' that indicates your current position in the file. The scroll bar will also show areas of the file where warnings or errors are detected by coloring the bar yellow or red, respectively. Tick marks will also be added to the left and right hand side of the bar, for search hits and bookmarks. Above and below the main body are status lines that display: * the current time; * the name of the file the top line was pulled from; * the log format for the top line; * the current view; * the line number for the top line in the display; * the current search hit and the total number of hits; * the number of lines not displayed because of filtering. Finally, the last line on the display is where you can enter search patterns and execute internal commands, such as converting a unix-timestamp into a human-readable date. The command-line is implemented using the readline library, so the usual set of keyboard shortcuts are available. Most commands and searches also support tab-completion. The body of the display is also used to display other content, such as: the help file, histograms of the log messages over time, and SQL results. The views are organized into a stack so that any time you activate a new view with a key press or command, the new view is pushed onto the stack. Pressing the same key again will pop the view off of the stack and return you to the previous view. Note that you can always use 'q' to pop the top view off of the stack. KEY BINDINGS ------------ To help navigate through the file there are many hotkeys that should make it easy to zero-in on a specific section of the file or scan through the file. ? View/leave this help message. q Leave the current view or quit the program when in the log file view. g/home Move to the top of the file. G/end Move to the end of the file. If the view is already at the end, it will move to the last line. space/pgdn Move down a page. b/bs/pgup Move up a page. j/cr/down-arrow Move down a line. k/up-arrow Move up a line. h/left-arrow Move to the left. l/right-arrow Move to the right. e/E Move to the next/previous error. w/W Move to the next/previous warning. n/N Move to the next/previous search hit. f/F Move to the next/previous file. In the log view, this moves to the next line from a different file. In the text view, this rotates the view to the next file. >/< Move horizontally to the next/previous search hit. t Switch to/from the text file view. The text file view is for any files that are not recognized as log files. o/O Move forward/backward 60 minutes from the current position in the log file. d/D Move forward/backward 24 hours from the current position in the log file. 1-6/Shift 1-6 Move to the next/previous n'th ten minute of the hour. For example, '4' would move to the first log line in the fortieth minute of the current hour in the log. And, '6' would move to the next hour boundary. 0/Shift 0 Move to the next/previous day boundary. m Mark/unmark the line at the top of the display. The line will be highlighted with reverse video to indicate that it is a user bookmark. You can use the 'u' hotkey to iterate through marks you have added. M Mark/unmark all the lines between the top of the display and the last line marked/unmarked. J Mark/unmark the next line after the previously marked line. K Like 'J' except it toggles the mark on the previous line. c Copy the marked text to the X11 selection buffer or OS X clipboard. C Clear all marked lines. u/U Move forward/backward through any user bookmarks you have added using the 'm' key. This hotkey will also jump to the start of any log partitions that have been created with the 'partition-name' command. T Toggle the display of the "elapsed time" column that shows the time elapsed since the beginning of the logs or the offset from the previous bookmark. Sharp changes in the message rate are highlighted by coloring the separator between the time column and the log message. A red highlight means the message rate has slowed down and green means it has sped up. You can use the "s/S" hotkeys to scan through the slow downs. s/S Move to the next/previous "slow down" in the log message rate. A slow down is detected by measuring how quickly the message rate has changed over the previous several messages. For example, if one message is logged every second for five seconds and then the last message arrives five seconds later, the last message will be highlighted as a slow down. i View/leave a histogram of the log messages over time. The histogram counts the number of displayed log lines for each bucket of time. The bars are layed out horizontally with colored segments representing the different log levels. You can use the 'z' hotkey to change the size of the time buckets (e.g. ten minutes, one hour, one day). I Switch between the log and histogram views while keeping the time displayed at the top of each view in sync. For example, if the top line in the log view is "11:40", hitting 'I' will switch to the histogram view and scrolled to display "11:00" at the top (if the zoom level is hours). z/Shift Z Zoom in or out one step in the histogram view. / Start a search for the given regular expression. The search is live, so when there is a pause in typing, the currently running search will be canceled and a new one started. History is maintained for your searches so you can rerun them easily. Words that are currently displayed are also available for tab-completion, so you can easily search for values without needing to copy-and-paste the string. If there is an error encountered while trying to interpret the expression, the error will be displayed in red on the status line. While the search is active, the 'hits' field in the status line will be green, when finished it will turn back to black. Note: The regular expression format used by is PCRE (Perl-Compatible Regular Expressions). For example, if you wanted to search for ethernet device names, regardless of their ID number, you can type: eth\d+ You can find more information about Perl regular expressions at: http://perldoc.perl.org/perlre.html If the search string is not valid PCRE, a search is done for the exact string instead of doing a regex search. : Execute an internal command. The commands are listed below. History is also supported in this context as well as tab-completion for commands and some arguments. The result of the command replaces the command you typed. ; Execute an SQL query. Most supported log file formats provide a sqlite virtual table backend that can be used in queries. See the SQL section below for more information. CTRL+] Abort command-line entry started with '/', ':', or ';'. y/Y Move forward/backward through the log view based on the "log_line" column in the SQL result view. v Switch to/from the SQL result view. V Switch between the log and SQL result views while keeping the top line number in the log view in sync with the log_line column in the SQL view. For example, doing a query that selects for "log_idle_msecs" and "log_line", you can move the top of the SQL view to a line and hit 'V' to switch to the log view and move to the line number that was selected in the "log_line" column. TAB/Shift+TAB In the SQL result view, cycle through the columns that are graphed. Initially, all number values are displayed in a stacked graph. Pressing TAB will change the display to only graph the first column. Repeatedly pressing TAB will cycle through the columns until they are all graphed again. p Enable or disable the display of the fields that the log message parser knows about or has discovered. This overlay is temporarily enabled when the semicolon key (;) is pressed so that it is easier to write queries. X Close the current text file or log file. CTRL-R Reset the session state. This will save the current session state (filters, highlights) and then reset the state to the factory default. CTRL-W Toggle word-wrapping. r/R Restore the next/previous session. The current session is saved and then the new state is restored. F2 Toggle mouse support. MOUSE SUPPORT (experimental) ---------------------------- If you are using Xterm, or a compatible terminal, you can use the mouse to mark lines of text and move the view by grabbing the scrollbar. NOTE: You need to manually enable this feature by setting the LNAV_EXP environment variable to "mouse". COMMANDS -------- help Switch to this help text view. adjust-log-time Change the time of the top log line to the given time. All other log lines in the same file will also be adjusted using the same offset. After the adjustment, the displayed timestamp will be rewritten to the new time and highlighted with a magenta color. This command is useful for lining up log files that have timestamps from different machines. unix-time Convert a unix-timestamp in seconds to a human-readable form or vice-versa. BEWARE OF TIMEZONE DIFFERENCES. current-time Print the current time in human-readable form and as a unix-timestamp. goto Go to the given line number, N percent into the file, or the given timestamp in the log view. If the line number is negative, it is considered an offset from the last line. highlight Highlight strings that match the given regular expression. filter-in Only display lines that match the given regular expression. This command can be used multiple times to add more lines to the display. The number of lines that are filtered out will be shown in the bottom status bar as 'Not Shown'. filter-out Do not display lines that match the given regular expression. This command can be used multiple times to remove more lines from the display. If a 'filter-in' expression is also active, it takes priority and the filter-out will remove lines that were matched by the 'filter-in'. The number of lines that are filtered out will be shown in the bottom status bar as 'Not Shown'. disable-filter Disable an active 'filter-in' or 'filter-out' expression. enable-filter Enable a inactive 'filter-in' or 'filter-out' expression. set-min-log-level Set the minimum level to display in the log view. You can use TAB to view the possible values. disable-word-wrap Disable word wrapping in the log and text file views. enable-word-wrap Enable word wrapping in the log and text file views. open [:] Open the given file within lnav and, if it is a text file, switch to the text view and jump to the given line number. close Close the current text file or log file. You can also close the current file by pressing 'X'. graph Graph the value of numbers in the file(s) over time. The given regular expression should capture the number to be displayed. For example: my stats: (\d+\.\d+) Will graph all the "stats" values found in the file. XXX This is still mostly a toy... append-to Append any marked lines to the given file. write-to Write any marked lines to the given file. write-csv-to Write the results of a SQL query to a CSV-formatted file. When running in non-interactive mode, a dash can be used to write to standard out. write-json-to Write the results of a SQL query to a JSON-formatted file. The contents of the file will be an array of objects with each column in the query being a field in the objects. When running in non-interactive mode, a dash can be used to write to standard out. session Add the given command to the session file (~/.lnav/session). Any commands listed in the session file are executed on startup. Only the highlight, word-wrap, and filter-related commands can be added to the session file. create-logline-table Create an SQL table using the top line of the log view as a template. See the "SQL QUERIES" and "DYNAMIC LOG LINE TABLE" sections below for more information. delete-logline-table Delete an SQL table created by the 'create-logline-table' command. switch-to-view Switch the display to the given view, which can be one of: help, log, text, histogram, db, and schema. partition-name Mark the top line in the log view as the start of a new partition with the given name. The current partition name will be reflected in the top status bar next to the current time as well as being available in the 'log_part' column of the SQL log tables. Partitions can be used to make it easier to query subsections of log messages. clear-partition Clear the partition the top line is a part of. SQL QUERIES (experimental) ----------- Lnav has support for performing SQL queries on log files using the Sqlite3 "virtual" table feature. For all supported log file types, lnav will create tables that can be queried using the subset of SQL that is supported by Sqlite3. For example, to get the top ten URLs being accessed in any loaded Apache log files, you can execute: ;select cs_uri_stem, count(*) as total from access_log group by cs_uri_stem order by total desc limit 10; The query result view shows the results and graphs any numeric values found in the result, much like the histogram view. The builtin set of log tables are listed below. Note that only the log messages that match a particular format can be queried by a particular table. You can find the file format and table name for the top log message by looking in the upper right hand corner of the log file view. The log table names are as follows: access_log Apache common access log format syslog_log Syslog format glog_log Google glog format strace_log Strace log format generic_log 'Generic' log format. This table contains messages from files that have a very simple format with a leading timestamp followed by the message. NOTE: You can get a dump of the schema for the internal tables, and any attached databases, by running the '.schema' SQL command. The columns available for the top log line in the view will automatically be displayed after pressing the semicolon (;) key. All log tables contain at least the following columns: log_line The line number in the file, starting at zero. log_part The name of the partition. Use the 'partition-name' command to mark the start of a new partition in the log view. log_time The time of the log entry. log_idle_msecs The amount of time, in milliseconds, between the current log message and the previous one. log_level The log level (e.g. info, error, etc...). log_mark The bookmark status for the line. This column can be written to using an UPDATE query. log_path The full path to the file. log_text The raw line of text. Note that this column is not included in the result of a 'select *', but it does exist. The following tables include the basic columns as listed above and include a few more columns since the log file format is more structured. syslog_log log_hostname The hostname the message was received from. log_procname The name of the process that sent the message. log_pid The process ID of the process that sent the message. access_log (The column names are the same as those in the Microsoft LogParser tool.) c_ip The client IP address. cs_username The client user name. cs_method The HTTP method. cs_uri_stem The stem portion of the URI. cs_uri_query The query portion of the URI. cs_version The HTTP version string. sc_status The status number returned to the client. sc_bytes The number of bytes sent to the client. cs_referrer The URL of the referring page. cs_user_agent The user agent string. strace_log (Currently, you need to run strace with the "-tt -T" options so there are timestamps for each function call.) funcname The name of the syscall. result The result code. duration The amount of time spent in the syscall. arg0 - arg9 The arguments passed to the syscall. These tables are created dynamically and not stored in memory or on disk. If you would like to persist some information from the tables, you can attach another database and create tables in that database. For example, if you wanted to save the results from the earlier example of a top ten query into the "/tmp/topten.db" file, you can do: ;attach database "/tmp/topten.db" as topten; ;create table topten.foo as select cs_uri_stem, count(*) as total from access_log group by cs_uri_stem order by total desc limit 10; DYNAMIC LOG LINE TABLE (experimental) ---------------------- (NOTE: This feature is still very new and not completely reliable yet, use with care.) For log formats that lack message structure, lnav can parse the log message and attempt to extract any data fields that it finds. This feature is available through the "logline" log table. This table is dynamically created and defined based on the message at the top of the log view. For example, given the following log message from "sudo", lnav will create the "logline" table with columns for "TTY", "PWD", "USER", and "COMMAND": May 24 06:48:38 Tim-Stacks-iMac.local sudo[76387]: stack : TTY=ttys003 ; PWD=/Users/stack/github/lbuild ; USER=root ; COMMAND=/bin/echo Hello, World! Queries executed against this table will then only return results for other log messages that have the same format. So, if you were to execute the following query while viewing the above line, you might get the following results: ;select USER,COMMAND from logline; USER | COMMAND ---- | ------------------------- root | /bin/echo Hello, World! mal | /bin/echo Goodbye, World! The log parser works by examining each message for key/value pairs separated by an equal sign (=) or a colon (:). For example, in the previous example of a "sudo" message, the parser sees the "USER=root" string as a pair where the key is "USER" and the value is "root". If no pairs can be found, then anything that looks like a value is extracted and assigned a numbered column. For example, the following line is from "dhcpd": Sep 16 22:35:57 drill dhcpd: DHCPDISCOVER from 00:16:ce:54:4e:f3 via hme3 In this case, the lnav parser recognizes that "DHCPDISCOVER", the MAC address and the "hme3" device name are values and not normal words. So, it builds a table with three columns for each of these values. The regular words in the message, like "from" and "via", are then used to find other messages with a similar format. If you would like to execute queries against log messages of different formats at the same time, you can use the 'create-logline-table' command to permanently create a table using the top line of the log view as a template. lnav-0.7.0/src/hist_source.cc000664 000765 000024 00000014133 12270770564 016371 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include "lnav_util.hh" #include "hist_source.hh" using namespace std; hist_source::hist_source() : hs_bucket_size(1), hs_group_size(100), hs_label_source(NULL), hs_token_bucket(NULL) { } void hist_source::text_value_for_line(textview_curses &tc, int row, std::string &value_out, bool no_scrub) { int grow = row / (this->buckets_per_group() + 1); int brow = row % (this->buckets_per_group() + 1); if (brow == 0) { unsigned long width; vis_line_t height; tc.get_dimensions(height, width); value_out.insert((unsigned int)0, width, '-'); if (this->hs_label_source != NULL) { this->hs_label_source->hist_label_for_group(grow, value_out); } this->hs_token_bucket = NULL; } else { std::map::iterator group_iter; bucket_t::iterator iter; int bucket_index; bucket_index = brow - 1; group_iter = this->hs_groups.begin(); advance(group_iter, grow); this->hs_token_bucket = &(group_iter->second[bucket_index]); if (this->hs_label_source != NULL) { this->hs_label_source-> hist_label_for_bucket((group_iter->first * this->hs_group_size) + (bucket_index * this->hs_bucket_size), *this->hs_token_bucket, value_out); } } } void hist_source::text_attrs_for_line(textview_curses &tc, int row, string_attrs_t &value_out) { int grow = row / (this->buckets_per_group() + 1); int brow = row % (this->buckets_per_group() + 1); int bucket_index = brow - 1; if (this->hs_token_bucket != NULL) { std::map::iterator group_iter; view_colors & vc = view_colors::singleton(); unsigned long width, avail_width; bucket_t::iterator iter; vis_line_t height; struct line_range lr; group_iter = this->hs_groups.begin(); advance(group_iter, grow); tc.get_dimensions(height, width); avail_width = width - this->hs_token_bucket->size(); bucket_stats_t overall_stats; for (std::map::iterator stats_iter = this->hs_bucket_stats.begin(); stats_iter != this->hs_bucket_stats.end(); ++stats_iter) { if (!this->is_bucket_graphed(stats_iter->first)) continue; overall_stats.merge(stats_iter->second); } lr.lr_start = 0; for (iter = this->hs_token_bucket->begin(); iter != this->hs_token_bucket->end(); iter++) { double percent = (double)(iter->second - overall_stats.bs_min_count) / overall_stats.width(); int amount, attrs; if (!this->is_bucket_graphed(iter->first)) continue; attrs = vc. reverse_attrs_for_role(this->get_role_for_type(iter->first)); amount = (int)rint(percent * avail_width); if (iter->second == 0.0) { amount = 0; } else { amount = max(1, amount); } lr.lr_end = lr.lr_start + amount; value_out.push_back(string_attr(lr, &view_curses::VC_STYLE, attrs)); lr.lr_start = lr.lr_end; } this->hs_label_source->hist_attrs_for_bucket( (group_iter->first * this->hs_group_size) + (bucket_index * this->hs_bucket_size), *this->hs_token_bucket, value_out); } } void hist_source::add_value(unsigned int value, bucket_type_t bt, bucket_count_t amount) { bucket_group_t bg; bg = bucket_group_t(value / this->hs_group_size); bucket_array_t &ba = this->hs_groups[bg]; if (ba.empty()) { ba.resize(this->buckets_per_group()); } bucket_count_t &bc = ba[(value % this->hs_group_size) / this->hs_bucket_size][bt]; bc += amount; bucket_stats_t &stats = this->hs_bucket_stats[bt]; stats.bs_max_count = max(stats.bs_max_count, bc); stats.bs_min_count = min(stats.bs_min_count, bc); } lnav-0.7.0/src/hist_source.hh000664 000765 000024 00000020030 12306074235 016364 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file hist_source.hh */ #ifndef __hist_source_hh #define __hist_source_hh #include #include #include #include #include #include "lnav_log.hh" #include "strong_int.hh" #include "textview_curses.hh" typedef float bucket_count_t; /** Type for indexes into a group of buckets. */ STRONG_INT_TYPE(int, bucket_group); /** Type used to differentiate values added to the same row in the histogram */ STRONG_INT_TYPE(int, bucket_type); /** * A text source that displays data as a histogram using horizontal bars. Data * is added to the histogram using the add_value() method. Once all of the * values have been added, the analyze() method needs to be called to analyze * the data so that it can be displayed. * * For example, if the values (7, 3, 4, 2) were added, they would be displayed * like so: * * ****** * *** * **** * ** */ class hist_source : public text_sub_source { public: typedef std::map bucket_t; /** * Source for labels on each bucket and group. */ class label_source { public: virtual ~label_source() { }; virtual void hist_label_for_group(int group, std::string &label_out) { }; virtual void hist_label_for_bucket(int bucket_start_value, const bucket_t &bucket, std::string &label_out) { }; virtual void hist_attrs_for_bucket(int bucket_start_value, const bucket_t &bucket, string_attrs_t &sa) { }; }; hist_source(); virtual ~hist_source() { }; void set_bucket_size(unsigned int bs) { require(bs > 0); this->hs_bucket_size = bs; }; unsigned int get_bucket_size(void) const { return this->hs_bucket_size; }; void set_group_size(unsigned int gs) { require(gs > 0); this->hs_group_size = gs; }; unsigned int get_group_size(void) const { return this->hs_group_size; }; void set_label_source(label_source *hls) { this->hs_label_source = hls; } label_source *get_label_source(void) { return this->hs_label_source; }; int buckets_per_group(void) const { return this->hs_group_size / this->hs_bucket_size; }; void clear(void) { this->hs_groups.clear(); this->hs_bucket_stats.clear(); }; size_t text_line_count() { return (this->buckets_per_group() + 1) * this->hs_groups.size(); }; void set_role_for_type(bucket_type_t bt, view_colors::role_t role) { this->hs_type2role[bt] = role; }; const view_colors::role_t &get_role_for_type(bucket_type_t bt) { return this->hs_type2role[bt]; }; void text_value_for_line(textview_curses &tc, int row, std::string &value_out, bool no_scrub); void text_attrs_for_line(textview_curses &tc, int row, string_attrs_t &value_out); size_t text_size_for_line(textview_curses &tc, int row, bool raw) { return 0; }; int value_for_row(vis_line_t row) { int grow = row / (this->buckets_per_group() + 1); int brow = row % (this->buckets_per_group() + 1); int retval = 0; if (!this->hs_groups.empty()) { std::map::const_iterator iter; iter = this->hs_groups.begin(); std::advance(iter, grow); bucket_group_t bg = iter->first; if (brow > 0) { brow -= 1; } retval = (bg * this->hs_group_size) + (brow * this->hs_bucket_size); } return retval; }; vis_line_t row_for_value(int value) { vis_line_t retval; if (!this->hs_groups.empty()) { bucket_group_t bg(value / this->hs_group_size); std::map::iterator lb; lb = this->hs_groups.lower_bound(bg); retval = vis_line_t(distance(this->hs_groups.begin(), lb) * (this->buckets_per_group() + 1)); retval += vis_line_t(1 + (value % this->hs_group_size) / this->hs_bucket_size); } return retval; }; /** * Add a value to the histogram. * * @param value The row in the histogram. * @param bt The type of data. * @param amount The amount to add to this row in the histogram. */ void add_value(unsigned int value, bucket_type_t bt, bucket_count_t amount = 1.0); void add_empty_value(unsigned int value) { bucket_group_t bg; bg = bucket_group_t(value / this->hs_group_size); bucket_array_t &ba = this->hs_groups[bg]; if (ba.empty()) { ba.resize(this->buckets_per_group()); } }; std::vector &get_displayed_buckets() { return this->hs_displayed_buckets; }; bool is_bucket_graphed(bucket_type_t type) const { return (this->hs_displayed_buckets.empty() || std::find(this->hs_displayed_buckets.begin(), this->hs_displayed_buckets.end(), type) != this->hs_displayed_buckets.end()); }; protected: typedef std::vector bucket_array_t; struct bucket_stats_t { bucket_stats_t() : bs_min_count(std::numeric_limits::max()), bs_max_count(0) { }; void merge(const bucket_stats_t &rhs) { this->bs_min_count = std::min(this->bs_min_count, rhs.bs_min_count); this->bs_max_count += rhs.bs_max_count; }; bucket_count_t width() const { return fabs(this->bs_max_count - this->bs_min_count); }; bucket_count_t bs_min_count; bucket_count_t bs_max_count; }; std::map hs_type2role; std::map hs_groups; std::map hs_bucket_stats; unsigned int hs_bucket_size; /* hours */ unsigned int hs_group_size; /* days */ label_source *hs_label_source; bucket_t *hs_token_bucket; std::vector hs_displayed_buckets; }; #endif lnav-0.7.0/src/init-sql.hh000664 000765 000024 00000003414 12211635053 015600 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file init-sql.hh */ #ifndef __init_sql_hh #define __init_sql_hh extern "C" { /** * The help message text. The value for this comes from the "init.sql" file, * which gets linked into the executable by the Makefile. */ extern const char init_sql[]; } #endif lnav-0.7.0/src/init.sql000664 000765 000024 00000005332 12315724711 015211 0ustar00stackstaff000000 000000 -- This file was created by init_sql.py -- CREATE TABLE IF NOT EXISTS http_status_codes ( status integer PRIMARY KEY, message text, FOREIGN KEY(status) REFERENCES access_log(sc_status) ); INSERT INTO http_status_codes VALUES (200, "OK"); INSERT INTO http_status_codes VALUES (201, "Created"); INSERT INTO http_status_codes VALUES (202, "Accepted"); INSERT INTO http_status_codes VALUES (203, "Non-Authoritative Information"); INSERT INTO http_status_codes VALUES (204, "No Content"); INSERT INTO http_status_codes VALUES (205, "Reset Content"); INSERT INTO http_status_codes VALUES (206, "Partial Content"); INSERT INTO http_status_codes VALUES (400, "Bad Request"); INSERT INTO http_status_codes VALUES (401, "Unauthorized"); INSERT INTO http_status_codes VALUES (402, "Payment Required"); INSERT INTO http_status_codes VALUES (403, "Forbidden"); INSERT INTO http_status_codes VALUES (404, "Not Found"); INSERT INTO http_status_codes VALUES (405, "Method Not Allowed"); INSERT INTO http_status_codes VALUES (406, "Not Acceptable"); INSERT INTO http_status_codes VALUES (407, "Proxy Authentication Required"); INSERT INTO http_status_codes VALUES (408, "Request Timeout"); INSERT INTO http_status_codes VALUES (409, "Conflict"); INSERT INTO http_status_codes VALUES (410, "Gone"); INSERT INTO http_status_codes VALUES (411, "Length Required"); INSERT INTO http_status_codes VALUES (412, "Precondition Failed"); INSERT INTO http_status_codes VALUES (413, "Request Entity Too Large"); INSERT INTO http_status_codes VALUES (414, "Request-URI Too Long"); INSERT INTO http_status_codes VALUES (415, "Unsupported Media Type"); INSERT INTO http_status_codes VALUES (416, "Requested Range Not Satisfiable"); INSERT INTO http_status_codes VALUES (417, "Expectation Failed"); INSERT INTO http_status_codes VALUES (100, "Continue"); INSERT INTO http_status_codes VALUES (101, "Switching Protocols"); INSERT INTO http_status_codes VALUES (300, "Multiple Choices"); INSERT INTO http_status_codes VALUES (301, "Moved Permanently"); INSERT INTO http_status_codes VALUES (302, "Found"); INSERT INTO http_status_codes VALUES (303, "See Other"); INSERT INTO http_status_codes VALUES (304, "Not Modified"); INSERT INTO http_status_codes VALUES (305, "Use Proxy"); INSERT INTO http_status_codes VALUES (306, "(Unused)"); INSERT INTO http_status_codes VALUES (307, "Temporary Redirect"); INSERT INTO http_status_codes VALUES (500, "Internal Server Error"); INSERT INTO http_status_codes VALUES (501, "Not Implemented"); INSERT INTO http_status_codes VALUES (502, "Bad Gateway"); INSERT INTO http_status_codes VALUES (503, "Service Unavailable"); INSERT INTO http_status_codes VALUES (504, "Gateway Timeout"); INSERT INTO http_status_codes VALUES (505, "HTTP Version Not Supported"); lnav-0.7.0/src/init_sql.py000775 000765 000024 00000000603 12315723176 015724 0ustar00stackstaff000000 000000 #! /usr/bin/env python import httplib TABLES = """ -- This file was created by init_sql.py -- CREATE TABLE IF NOT EXISTS http_status_codes ( status integer PRIMARY KEY, message text, FOREIGN KEY(status) REFERENCES access_log(sc_status) ); """ print TABLES for item in httplib.responses.iteritems(): print "INSERT INTO http_status_codes VALUES (%d, \"%s\");" % item lnav-0.7.0/src/k_merge_tree.h000664 000765 000024 00000030241 12236377676 016343 0ustar00stackstaff000000 000000 /* K-Way Merge Template By Jordan Zimmerman */ #ifndef KMERGE_TREE_H #define KMERGE_TREE_H /* K-Way Merge An implementation of "k-Way Merging" as described in "Fundamentals of Data Structures" by Horowitz/Sahni. The idea is to merge k sorted arrays limiting the number of comparisons. A tree is built containing the results of comparing the heads of each array. The top most node is always the smallest entry. Then, its corresponding leaf in the tree is refilled and the tree is processed again. It's easier to see in the following example: Imagine 4 sorted arrays: {5, 10, 15, 20} {10, 13, 16, 19} {2, 19, 26, 40} {18, 22, 23, 24} The initial tree looks like this: 2 / \ 2 5 / \ / \ 18 2 10 5 The '/' and '\' represent links. The bottom row has the leaves and they contain the heads of the arrays. The rows above the leaves represent the smaller of the two child nodes. Thus, the top node is the smallest. To process the next iteration, the top node gets popped and its leaf gets refilled. Then, the new leaf's associated nodes are processed. So, after the 2 is taken, it is filled with 19 (the next head of its array). After processing, the tree looks like this: 5 / \ 18 5 / \ / \ 18 19 10 5 So, you can see how the number of comparisons is reduced. A good use of this is when you have a very large array that needs to be sorted. Break it up into n small arrays and sort those. Then use this merge sort for the final sort. This can also be done with files. If you have n sorted files, you can merge them into one sorted file. K Way Merging works best when comparing is somewhat expensive. */ #include #include template > class kmerge_tree_c { public: // create the tree with the given number of buckets. Call add() for each of the buckets // and then call execute() to build things. Call get_top() then next() until get_top returns // false. kmerge_tree_c(long bucket_qty); ~kmerge_tree_c(); // add a sorted collection to the tree // // begin/end - start end of a collection void add(owner_t *owner, iterator_t begin, iterator_t end); // process the first sort void execute(void); // advance to the next entry void next(void); // return the next entry without re-processing the tree // if false is returned, the merge is complete bool get_top(owner_t *&owner, iterator_t& iterator) { if (top_node_ptr_mbr->has_iterator) { owner = top_node_ptr_mbr->owner_ptr; iterator = top_node_ptr_mbr->current_iterator; return iterator != top_node_ptr_mbr->end_iterator; } else { return false; } } private: class node_rec { public: node_rec(void) : left_child_ptr(NULL), right_child_ptr(NULL), parent_ptr(NULL), next_ptr(NULL), previous_ptr(NULL), next_leaf_ptr(NULL), source_node_ptr(NULL), owner_ptr(NULL), has_iterator(false) { } ~node_rec() { delete left_child_ptr; delete right_child_ptr; } node_rec* left_child_ptr; // owned the left child of this node node_rec* right_child_ptr; // owned the right child of this node node_rec* parent_ptr; // copy the parent of this node node_rec* next_ptr; // copy the next sibling node_rec* previous_ptr; // copy the previous sibling node_rec* next_leaf_ptr; // copy only for the bottom rows, a linked list of the buckets node_rec* source_node_ptr; // copy ptr back to the node from whence this iterator came owner_t *owner_ptr; int has_iterator; iterator_t current_iterator; iterator_t end_iterator; private: node_rec(const node_rec&); node_rec& operator=(const node_rec&); }; void build_tree(void); node_rec* build_levels(long number_of_levels); void build_left_siblings(kmerge_tree_c::node_rec* node_ptr); void build_right_siblings(kmerge_tree_c::node_rec* node_ptr); void compare_nodes(kmerge_tree_c::node_rec* node_ptr); comparitor comparitor_mbr; long bucket_qty_mbr; long number_of_levels_mbr; node_rec* top_node_ptr_mbr; // owned node_rec* first_leaf_ptr; // copy node_rec* last_leaf_ptr; // copy }; inline long kmerge_tree_brute_log2(long value) { long square = 2; long count = 1; while ( square < value ) { square *= 2; ++count; } return count; } // kmerge_tree_brute_log2 //~~~~~~~~~~class kmerge_tree_c template kmerge_tree_c::kmerge_tree_c(long bucket_qty) : bucket_qty_mbr(bucket_qty), number_of_levels_mbr(bucket_qty ? ::kmerge_tree_brute_log2(bucket_qty_mbr) : 0), // don't add one - build_levels is zero based top_node_ptr_mbr(NULL), first_leaf_ptr(NULL), last_leaf_ptr(NULL) { build_tree(); } template kmerge_tree_c::~kmerge_tree_c() { delete top_node_ptr_mbr; } /* Unlike the book, I'm going to make my life easy by maintaining every possible link to each node that I might need */ template void kmerge_tree_c::build_tree(void) { // the book says that the number of levels is (log2 * k) + 1 top_node_ptr_mbr = build_levels(number_of_levels_mbr); if ( top_node_ptr_mbr ) { build_left_siblings(top_node_ptr_mbr); build_right_siblings(top_node_ptr_mbr); } } /* highly recursive tree builder as long as number_of_levels isn't zero, each node builds its own children and updates the parent link for them. If no children are to be built (i.e. number_of_levels is 0), then the leaf linked list is created */ template typename kmerge_tree_c::node_rec * kmerge_tree_c::build_levels(long number_of_levels) { node_rec* node_ptr = new node_rec; if ( number_of_levels ) { node_ptr->left_child_ptr = build_levels(number_of_levels - 1); if ( node_ptr->left_child_ptr ) { node_ptr->left_child_ptr->parent_ptr = node_ptr; node_ptr->right_child_ptr = build_levels(number_of_levels - 1); if ( node_ptr->right_child_ptr ) { node_ptr->right_child_ptr->parent_ptr = node_ptr; } } } else { if ( last_leaf_ptr ) { last_leaf_ptr->next_leaf_ptr = node_ptr; last_leaf_ptr = node_ptr; } else { first_leaf_ptr = last_leaf_ptr = node_ptr; } } return node_ptr; } /* when we process a comparison, we'll have to compare two siblings this code matches each link with its sibling To get every node correct, I had to write two routines: one which works with left nodes and one which works with right nodes. build_tree() starts it off with the top node's children and then these two swing back and forth between each other. */ template void kmerge_tree_c::build_left_siblings(kmerge_tree_c::node_rec* node_ptr) { if ( node_ptr->parent_ptr ) { if ( node_ptr->parent_ptr->right_child_ptr ) { node_ptr->next_ptr = node_ptr->parent_ptr->right_child_ptr; node_ptr->parent_ptr->right_child_ptr->previous_ptr = node_ptr; } } if ( node_ptr->left_child_ptr ) { build_left_siblings(node_ptr->left_child_ptr); } if ( node_ptr->right_child_ptr ) { build_right_siblings(node_ptr->right_child_ptr); } } template void kmerge_tree_c::build_right_siblings(kmerge_tree_c::node_rec* node_ptr) { if ( node_ptr->parent_ptr ) { if ( node_ptr->parent_ptr->left_child_ptr ) { node_ptr->previous_ptr = node_ptr->parent_ptr->left_child_ptr; node_ptr->parent_ptr->left_child_ptr->next_ptr = node_ptr; } } if ( node_ptr->right_child_ptr ) { build_right_siblings(node_ptr->right_child_ptr); } if ( node_ptr->left_child_ptr ) { build_left_siblings(node_ptr->left_child_ptr); } } // fill the leaf linked list template void kmerge_tree_c::add(owner_t *owner, iterator_t begin, iterator_t end) { if ( begin == end ) { return; } node_rec* node_ptr = first_leaf_ptr; while ( node_ptr ) { if ( node_ptr->has_iterator ) { node_ptr = node_ptr->next_leaf_ptr; } else { node_ptr->has_iterator = true; node_ptr->owner_ptr = owner; node_ptr->current_iterator = begin; node_ptr->end_iterator = end; break; } } } /* fill the initial tree by comparing each sibling in the leaf linked list and then factoring that up to the parents This is only done once so it doesn't have to be that efficient */ template void kmerge_tree_c::execute(void) { for ( long parent_level = 0; parent_level < number_of_levels_mbr; ++parent_level ) { // the number of nodes to skip is (parent level + 1) ^ 2 - 1 long skip_nodes = 2; for ( long skip = 0; skip < parent_level; ++skip ) { skip_nodes *= 2; } --skip_nodes; node_rec* node_ptr = first_leaf_ptr; while ( node_ptr ) { node_rec* parent_ptr = node_ptr; long i; for ( i = 0; i < parent_level; ++i ) { parent_ptr = parent_ptr->parent_ptr; } compare_nodes(parent_ptr); for ( i = 0; i < skip_nodes; ++i ) { node_ptr = node_ptr->next_leaf_ptr; } node_ptr = node_ptr->next_leaf_ptr; } } } // compare the given node and its sibling and bubble the result up to the parent template void kmerge_tree_c::compare_nodes(kmerge_tree_c::node_rec* node_ptr) { // assert(node_ptr->parent_ptr); node_rec* node1_ptr = NULL; node_rec* node2_ptr = NULL; if ( node_ptr->next_ptr ) { node1_ptr = node_ptr; node2_ptr = node_ptr->next_ptr; } else { node1_ptr = node_ptr->previous_ptr; node2_ptr = node_ptr; } long result; if ( !node2_ptr->has_iterator ) { result = -1; } else if ( !node1_ptr->has_iterator) { result = 1; } else if ( (node1_ptr->current_iterator != node1_ptr->end_iterator) && (node2_ptr->current_iterator != node2_ptr->end_iterator) ) { // no need to check for exact equality - we just want the lesser of the two result = comparitor_mbr(*node1_ptr->current_iterator, *node2_ptr->current_iterator) ? -1 : 1; } else if ( node1_ptr->current_iterator != node1_ptr->end_iterator ) { result = -1; } else // if ( node2_ptr->current_iterator != node2_ptr->end_iterator ) { result = 1; } node_rec* winner_ptr = (result <= 0) ? node1_ptr : node2_ptr; node_rec* parent_ptr = node_ptr->parent_ptr; parent_ptr->owner_ptr = winner_ptr->owner_ptr; parent_ptr->has_iterator = winner_ptr->has_iterator; parent_ptr->current_iterator = winner_ptr->current_iterator; parent_ptr->end_iterator = winner_ptr->end_iterator; parent_ptr->source_node_ptr = winner_ptr; } /* pop the top node, factor it down the list to find its leaf, replace its leaf and then factor that back up */ template void kmerge_tree_c::next(void) { if ( top_node_ptr_mbr->current_iterator == top_node_ptr_mbr->end_iterator ) { return; } // find the source leaf ptr node_rec* node_ptr = top_node_ptr_mbr; while ( node_ptr->source_node_ptr ) { node_ptr = node_ptr->source_node_ptr; } // assert(!node_ptr->left_child_ptr && !node_ptr->right_child_ptr); // assert(top_node_ptr_mbr->current_iterator == node_ptr->current_iterator); ++node_ptr->current_iterator; while ( node_ptr->parent_ptr ) { compare_nodes(node_ptr); node_ptr = node_ptr->parent_ptr; } } #endif // KMERGE_TREE_H lnav-0.7.0/src/line_buffer.cc000664 000765 000024 00000043730 12312022473 016311 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file line_buffer.cc */ #include "config.h" #include #include #include #include #include #ifdef HAVE_BZLIB_H #include #endif #include #include "line_buffer.hh" using namespace std; static const size_t DEFAULT_LINE_BUFFER_SIZE = 256 * 1024; static const size_t MAX_LINE_BUFFER_SIZE = 4 * DEFAULT_LINE_BUFFER_SIZE; static const size_t DEFAULT_INCREMENT = 128 * 1024; static const size_t MAX_COMPRESSED_BUFFER_SIZE = 32 * 1024 * 1024; /* * XXX REMOVE ME * * The stock gzipped file code does not use pread, so we need to use a lock to * get exclusive access to the file. In the future, we should just rewrite * the gzipped file code to use pread. */ class lock_hack { public: class guard { public: guard() : g_lock(lock_hack::singleton()) { this->g_lock.lock(); }; ~guard() { this->g_lock.unlock(); }; private: lock_hack &g_lock; }; static lock_hack &singleton() { static lock_hack retval; return retval; }; void lock() { lockf(this->lh_fd, F_LOCK, 0); }; void unlock() { lockf(this->lh_fd, F_ULOCK, 0); }; private: lock_hack() { char lockname[64]; snprintf(lockname, sizeof(lockname), "/tmp/lnav.%d.lck", getpid()); this->lh_fd = open(lockname, O_CREAT | O_RDWR, 0600); fcntl(this->lh_fd, F_SETFD, FD_CLOEXEC); unlink(lockname); }; int lh_fd; }; /* XXX END */ line_buffer::line_buffer() : lb_gz_file(NULL), lb_bz_file(false), lb_gz_offset(0), lb_file_size((size_t)-1), lb_file_offset(0), lb_file_time(0), lb_buffer_size(0), lb_buffer_max(DEFAULT_LINE_BUFFER_SIZE), lb_seekable(false), lb_last_line_offset(-1) { if ((this->lb_buffer = (char *)malloc(this->lb_buffer_max)) == NULL) { throw bad_alloc(); } ensure(this->invariant()); } line_buffer::~line_buffer() { auto_fd fd = -1; // Make sure any shared refs take ownership of the data. this->lb_share_manager.invalidate_refs(); this->set_fd(fd); } void line_buffer::set_fd(auto_fd &fd) throw (error) { off_t newoff = 0; if (this->lb_gz_file) { gzclose(this->lb_gz_file); this->lb_gz_file = NULL; } if (this->lb_bz_file) { this->lb_bz_file = false; } if (fd != -1) { /* Sync the fd's offset with the object. */ newoff = lseek(fd, 0, SEEK_CUR); if (newoff == -1) { if (errno != ESPIPE) { throw error(errno); } /* It's a pipe, start with a zero offset. */ newoff = 0; this->lb_seekable = false; } else { char gz_id[2 + 1 + 1 + 4]; if (pread(fd, gz_id, sizeof(gz_id), 0) == sizeof(gz_id)) { if (gz_id[0] == '\037' && gz_id[1] == '\213') { int gzfd = dup(fd); fcntl(gzfd, F_SETFD, FD_CLOEXEC); lseek(fd, 0, SEEK_SET); if ((this->lb_gz_file = gzdopen(gzfd, "r")) == NULL) { if (errno == 0) { throw bad_alloc(); } else{ throw error(errno); } } this->lb_file_time = *((int32_t *)&gz_id[4]); if (this->lb_file_time < 0) this->lb_file_time = 0; this->lb_gz_offset = lseek(this->lb_fd, 0, SEEK_CUR); } #ifdef HAVE_BZLIB_H else if (gz_id[0] == 'B' && gz_id[1] == 'Z') { lseek(fd, 0, SEEK_SET); this->lb_bz_file = true; /* * Loading data from a bzip2 file is pretty slow, so we try * to keep as much in memory as possible. */ this->resize_buffer(MAX_COMPRESSED_BUFFER_SIZE); } #endif } this->lb_seekable = true; } } this->lb_file_offset = newoff; this->lb_buffer_size = 0; this->lb_fd = fd; ensure(this->invariant()); } void line_buffer::resize_buffer(size_t new_max) throw (error) { char *tmp, *old; require(this->lb_bz_file || this->lb_gz_file || new_max <= MAX_LINE_BUFFER_SIZE); /* Still need more space, try a realloc. */ old = this->lb_buffer.release(); tmp = (char *)realloc(old, new_max); if (tmp != NULL) { this->lb_buffer = tmp; this->lb_buffer_max = new_max; } else { this->lb_buffer = old; throw error(ENOMEM); } } void line_buffer::ensure_available(off_t start, size_t max_length) throw (error) { size_t prefill, available; require(max_length <= MAX_LINE_BUFFER_SIZE); /* * Check to see if the start is inside the cached range or immediately * after. */ if (start < this->lb_file_offset || start > (off_t)(this->lb_file_offset + this->lb_buffer_size)) { /* * The request is outside the cached range, need to reload the * whole thing. */ prefill = 0; this->lb_buffer_size = 0; if ((this->lb_file_size != (size_t)-1) && (start + this->lb_buffer_max > this->lb_file_size)) { /* * If the start is near the end of the file, move the offset back a * bit so we can get more of the file in the cache. */ this->lb_file_offset = this->lb_file_size - std::min(this->lb_file_size, this->lb_buffer_max); } else { this->lb_file_offset = start; } } else { /* The request is in the cached range. Record how much extra data is in * the buffer before the requested range. */ prefill = start - this->lb_file_offset; } require(this->lb_file_offset <= start); require(prefill <= this->lb_buffer_size); available = this->lb_buffer_max - (start - this->lb_file_offset); require(available <= this->lb_buffer_max); if (max_length > available) { /* * Need more space, move any existing data to the front of the * buffer. */ this->lb_buffer_size -= prefill; this->lb_file_offset += prefill; memmove(&this->lb_buffer[0], &this->lb_buffer[prefill], this->lb_buffer_size); available = this->lb_buffer_max - (start - this->lb_file_offset); if (max_length > available) { this->resize_buffer(this->lb_buffer_max + DEFAULT_LINE_BUFFER_SIZE); } this->lb_share_manager.invalidate_refs(); } } bool line_buffer::fill_range(off_t start, size_t max_length) throw (error) { bool retval = false; require(start >= 0); if (this->in_range(start) && this->in_range(start + max_length - 1)) { /* Cache already has the data, nothing to do. */ retval = true; } else if (this->lb_fd != -1) { ssize_t rc; /* Make sure there is enough space, then */ this->ensure_available(start, max_length); /* ... read in the new data. */ if (this->lb_gz_file) { if (this->lb_file_size != (size_t)-1 && this->in_range(start) && this->in_range(this->lb_file_size - 1)) { rc = 0; } else { lock_hack::guard guard; lseek(this->lb_fd, this->lb_gz_offset, SEEK_SET); gzseek(this->lb_gz_file, this->lb_file_offset + this->lb_buffer_size, SEEK_SET); rc = gzread(this->lb_gz_file, &this->lb_buffer[this->lb_buffer_size], this->lb_buffer_max - this->lb_buffer_size); this->lb_gz_offset = lseek(this->lb_fd, 0, SEEK_CUR); } } #ifdef HAVE_BZLIB_H else if (this->lb_bz_file) { if (this->lb_file_size != (size_t)-1 && (((size_t)start >= this->lb_file_size) || (this->in_range(start) && this->in_range(this->lb_file_size - 1)))) { rc = 0; } else { lock_hack::guard guard; char scratch[32 * 1024]; BZFILE * bz_file; off_t seek_to; /* * Unfortunately, there is no bzseek, so we need to reopen the * file every time we want to do a read. */ lseek(this->lb_fd, 0, SEEK_SET); if ((bz_file = BZ2_bzdopen(dup(this->lb_fd), "r")) == NULL) { if (errno == 0) { throw bad_alloc(); } else{ throw error(errno); } } seek_to = this->lb_file_offset + this->lb_buffer_size; while (seek_to > 0) { int count; count = BZ2_bzread(bz_file, scratch, std::min((size_t)seek_to, sizeof(scratch))); seek_to -= count; } rc = BZ2_bzread(bz_file, &this->lb_buffer[this->lb_buffer_size], this->lb_buffer_max - this->lb_buffer_size); BZ2_bzclose(bz_file); if (rc != -1 && ( rc < (this->lb_buffer_max - this->lb_buffer_size))) { this->lb_file_size = ( this->lb_file_offset + this->lb_buffer_size + rc); } } } #endif else if (this->lb_seekable) { rc = pread(this->lb_fd, &this->lb_buffer[this->lb_buffer_size], this->lb_buffer_max - this->lb_buffer_size, this->lb_file_offset + this->lb_buffer_size); } else { rc = read(this->lb_fd, &this->lb_buffer[this->lb_buffer_size], this->lb_buffer_max - this->lb_buffer_size); } // XXX For some reason, cygwin is giving us a bogus return value when // up to the end of the file. if (rc > (this->lb_buffer_max - this->lb_buffer_size)) { rc = -1; #ifdef ENODATA errno = ENODATA; #else errno = EAGAIN; #endif } switch (rc) { case 0: if (!this->lb_seekable) { this->lb_file_size = this->lb_file_offset + this->lb_buffer_size; } if (start < (off_t) this->lb_file_size) { retval = true; } if (this->lb_gz_file || this->lb_bz_file) { /* * For compressed files, increase the buffer size so we don't * have to spend as much time uncompressing the data. */ this->resize_buffer(MAX_COMPRESSED_BUFFER_SIZE); } break; case (ssize_t)-1: switch (errno) { #ifdef ENODATA /* Cygwin seems to return this when pread reaches the end of the */ /* file. */ case ENODATA: #endif case EINTR: case EAGAIN: break; default: throw error(errno); } break; default: this->lb_buffer_size += rc; retval = true; break; } ensure(this->lb_buffer_size <= this->lb_buffer_max); } return retval; } bool line_buffer::read_line(off_t &offset, line_value &lv, bool include_delim) throw (error) { size_t request_size = DEFAULT_INCREMENT; bool retval = false; require(this->lb_fd != -1); if (this->lb_last_line_offset != -1 && offset > this->lb_last_line_offset) { /* * Don't return anything past the last known line. The caller needs * to try reading at the offset of the last line again. */ return false; } lv.lv_len = 0; lv.lv_partial = false; while (!retval) { char *line_start, *lf; this->fill_range(offset, request_size); /* Find the data in the cache and */ line_start = this->get_range(offset, lv.lv_len); /* ... look for the end-of-line or end-of-file. */ if (((lf = (char *)memchr(line_start, '\n', lv.lv_len)) != NULL) || (lv.lv_len >= MAX_LINE_BUFFER_SIZE) || (request_size == MAX_LINE_BUFFER_SIZE) || ((request_size > lv.lv_len) && lv.lv_len > 0)) { if ((lf != NULL) && ((lf - line_start) >= MAX_LINE_BUFFER_SIZE - 1)) { lf = NULL; } if (lf != NULL) { lv.lv_partial = false; lv.lv_len = lf - line_start; if (include_delim) { lv.lv_len += 1; } else { offset += 1; /* Skip the delimiter. */ } if (offset >= this->lb_last_line_offset) { this->lb_last_line_offset = offset + lv.lv_len; } } else { if (lv.lv_len >= MAX_LINE_BUFFER_SIZE) { lv.lv_len = MAX_LINE_BUFFER_SIZE - 1; lv.lv_partial = false; } else { lv.lv_partial = true; } /* * Be nice and make sure there is room for the caller to * add a NULL-terminator. */ this->ensure_available(offset, lv.lv_len + 1); line_start = this->get_range(offset, lv.lv_len); if (lv.lv_len >= MAX_LINE_BUFFER_SIZE) { lv.lv_len = MAX_LINE_BUFFER_SIZE - 1; } if (lv.lv_partial) { /* * Since no delimiter was seen, we need to remember the offset * of the last line in the file so we don't mistakenly return * two partial lines to the caller. * * 1. read_line() - returns partial line * 2. file is written * 3. read_line() - returns the middle of partial line. */ this->lb_last_line_offset = offset; } else if (offset >= this->lb_last_line_offset) { this->lb_last_line_offset = offset + lv.lv_len; } } lv.lv_start = line_start; offset += lv.lv_len; retval = true; } else { request_size += DEFAULT_INCREMENT; } if (!retval && !this->fill_range(offset, request_size)) { break; } } ensure(lv.lv_len <= this->lb_buffer_size); ensure(!retval || (lv.lv_start >= this->lb_buffer && (lv.lv_start + lv.lv_len) <= (this->lb_buffer + this->lb_buffer_size))); ensure(this->invariant()); return retval; } bool line_buffer::read_line(off_t &offset_inout, shared_buffer_ref &sbr) throw (error) { line_value lv; bool retval; // Clear the incoming ref right away so that an invalidate // does not cause a wasted malloc/copy. sbr.disown(); if ((retval = this->read_line(offset_inout, lv))) { sbr.share(this->lb_share_manager, lv.lv_start, lv.lv_len); } return retval; } bool line_buffer::read_range(off_t offset, size_t len, shared_buffer_ref &sbr) throw (error) { char *line_start; size_t avail; sbr.disown(); if (this->lb_last_line_offset != -1 && offset > this->lb_last_line_offset) { /* * Don't return anything past the last known line. The caller needs * to try reading at the offset of the last line again. */ return false; } this->fill_range(offset, len); line_start = this->get_range(offset, avail); sbr.share(this->lb_share_manager, line_start, len); return true; } lnav-0.7.0/src/line_buffer.hh000664 000765 000024 00000021112 12311035743 016314 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file line_buffer.hh */ #ifndef __line_buffer_hh #define __line_buffer_hh #include #include #include #include #include #include "lnav_log.hh" #include "auto_fd.hh" #include "auto_mem.hh" #include "shared_buffer.hh" struct line_value { char *lv_start; size_t lv_len; bool lv_partial; void terminate() { this->lv_start[this->lv_len] = '\0'; }; }; /** * Buffer for reading whole lines out of file descriptors. The class presents * a stateless interface, callers specify the offset where a line starts and * the class takes care of caching the surrounding range and locating the * delimiter. * * XXX A bit of a wheel reinvention, but I'm not sure how well the libraries * handle non-blocking I/O... */ class line_buffer { public: class error : public std::exception { public: error(int err) : e_err(err) { }; int e_err; }; /** Construct an empty line_buffer. */ line_buffer(); virtual ~line_buffer(); /** @param fd The file descriptor that data should be pulled from. */ void set_fd(auto_fd &fd) throw (error); /** @return The file descriptor that data should be pulled from. */ int get_fd() const { return this->lb_fd; }; time_t get_file_time() const { return this->lb_file_time; }; /** * @return The size of the file or the amount of data pulled from a pipe. */ ssize_t get_file_size() const { return this->lb_file_size; }; bool is_compressed() const { return this->lb_gz_file != NULL || this->lb_bz_file; }; off_t get_read_offset(off_t off) const { if (this->lb_gz_file) { return this->lb_gz_offset; } else{ return off; } }; /** * Read up to the end of file or a given delimiter. * * @param offset_inout The offset in the file to start reading from. On * return, it contains the offset where the next line should start or one * past the size of the file. * @param len_out On return, contains the length of the line, not including * the delimiter. * @param delim The character that splits lines in the input, defaults to a * line feed. * @return The address in the internal buffer where the line starts. The * line is not NULL-terminated, but this method ensures there is room to NULL * terminate the line. If any modifications are made to the line, such as * NULL termination, the invalidate() must be called before re-reading the * line to refresh the buffer. */ bool read_line(off_t &offset_inout, line_value &lv, bool include_delim = false) throw (error); bool read_line(off_t &offset_inout, shared_buffer_ref &sbr) throw (error); bool read_range(off_t offset, size_t len, shared_buffer_ref &sbr) throw (error); /** * Signal that the contents of the internal buffer have been modified and * any attempts to re-read the currently cached line(s) should trigger * another read from the file. */ void invalidate() { this->lb_file_offset += this->lb_buffer_size; this->lb_buffer_size = 0; this->lb_file_size = -1; log_info("invalidate %p", this); }; /** Release any resources held by this object. */ void reset() { this->lb_fd.reset(); this->lb_file_offset = 0; this->lb_file_size = (size_t)-1; this->lb_buffer_size = 0; this->lb_last_line_offset = -1; }; /** Check the invariants for this object. */ bool invariant(void) { require(this->lb_buffer != NULL); require(this->lb_buffer_size <= this->lb_buffer_max); return true; }; private: /** * @param off The file offset to check for in the buffer. * @return True if the given offset is cached in the buffer. */ bool in_range(off_t off) const { return this->lb_file_offset <= off && off < (int)(this->lb_file_offset + this->lb_buffer_size); }; void resize_buffer(size_t new_max) throw (error); /** * Ensure there is enough room in the buffer to cache a range of data from * the file. First, this method will check to see if there is enough room * from where 'start' begins in the buffer to the maximum buffer size. If * this is not enough, the currently cached data at 'start' will be moved * to the beginning of the buffer, overwriting any cached data earlier in * the file. Finally, if this is still not enough, the buffer will be * reallocated to make more room. * * @param start The file offset of the start of the line. * @param max_length The amount of data to be cached in the buffer. */ void ensure_available(off_t start, size_t max_length) throw (error); /** * Fill the buffer with the given range of data from the file. * * @param start The file offset where data should start to be read from the * file. * @param max_length The maximum amount of data to read from the file. * @return True if any data was read from the file. */ bool fill_range(off_t start, size_t max_length) throw (error); /** * After a successful fill, the cached data can be retrieved with this * method. * * @param start The file offset to retrieve cached data for. * @param avail_out On return, the amount of data currently cached at the * given offset. * @return A pointer to the start of the cached data in the internal * buffer. */ char *get_range(off_t start, size_t &avail_out) { off_t buffer_offset = start - this->lb_file_offset; char *retval; require(buffer_offset >= 0); retval = &this->lb_buffer[buffer_offset]; avail_out = this->lb_buffer_size - buffer_offset; return retval; }; shared_buffer lb_share_manager; auto_fd lb_fd; /*< The file to read data from. */ gzFile lb_gz_file; /*< File handle for gzipped files. */ bool lb_bz_file; /*< Flag set for bzip2 compressed files. */ off_t lb_gz_offset; /*< The offset into the compressed file. */ auto_mem lb_buffer; /*< The internal buffer where data is cached */ ssize_t lb_file_size; /*< * The size of the file. When lb_fd refers to * a pipe, this is set to the amount of data * read from the pipe when EOF is reached. */ off_t lb_file_offset; /*< * Data cached in the buffer comes from this * offset in the file. */ time_t lb_file_time; ssize_t lb_buffer_size; /*< The amount of cached data in the buffer. */ ssize_t lb_buffer_max; /*< The size of the buffer memory. */ bool lb_seekable; /*< Flag set for seekable file descriptors. */ off_t lb_last_line_offset; /*< */ }; #endif lnav-0.7.0/src/listview_curses.cc000664 000765 000024 00000026120 12307030325 017254 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file listview_curses.cc */ #include "config.h" #include #include #include #include "lnav_log.hh" #include "listview_curses.hh" using namespace std; list_gutter_source listview_curses::DEFAULT_GUTTER_SOURCE; listview_curses::listview_curses() : lv_source(NULL), lv_overlay_source(NULL), lv_window(NULL), lv_y(0), lv_top(0), lv_left(0), lv_height(0), lv_needs_update(true), lv_show_scrollbar(true), lv_show_bottom_border(false), lv_gutter_source(&DEFAULT_GUTTER_SOURCE), lv_word_wrap(false), lv_scroll_accel(0), lv_scroll_velo(0), lv_mouse_y(-1), lv_mouse_mode(LV_MODE_NONE) { } listview_curses::~listview_curses() { } void listview_curses::reload_data(void) { if (this->lv_source == NULL) { this->lv_top = vis_line_t(0); this->lv_left = 0; } else if (this->lv_top >= this->get_inner_height()) { this->lv_top = max(vis_line_t(0), vis_line_t(this->get_inner_height() - 1)); } this->lv_needs_update = true; } bool listview_curses::handle_key(int ch) { vis_line_t height(0); unsigned long width; bool retval = true; this->get_dimensions(height, width); switch (ch) { case 'l': case KEY_RIGHT: this->shift_left(width / 2); break; case 'h': case KEY_LEFT: this->shift_left(-(width / 2)); break; case '\r': case 'j': case KEY_DOWN: this->shift_top(vis_line_t(1)); break; case 'k': case KEY_UP: this->shift_top(vis_line_t(-1)); break; case 'b': case KEY_BACKSPACE: case KEY_PPAGE: this->shift_top(-(this->rows_available(this->lv_top, RD_UP) - vis_line_t(1))); break; case ' ': case KEY_NPAGE: this->shift_top(this->rows_available(this->lv_top, RD_DOWN) - vis_line_t(1)); break; case 'g': case KEY_HOME: this->set_top(vis_line_t(0)); break; case 'G': case KEY_END: { vis_line_t last_line(this->get_inner_height() - 1); vis_line_t tail_bottom(this->get_top_for_last_row()); if (this->get_top() == last_line) this->set_top(tail_bottom); else if (tail_bottom <= this->get_top()) this->set_top(last_line); else this->set_top(tail_bottom); } break; case 'A': { double tenth = ((double)this->get_inner_height()) / 10.0; this->shift_top(vis_line_t((int)tenth)); } break; case 'B': { double tenth = ((double)this->get_inner_height()) / 10.0; this->shift_top(vis_line_t((int)-tenth)); } break; default: retval = false; break; } return retval; } void listview_curses::do_update(void) { if (this->lv_window != NULL && this->lv_needs_update) { vis_line_t y(this->lv_y), height, bottom, row; attr_line_t overlay_line; vis_line_t overlay_height(0); struct line_range lr; unsigned long width, wrap_width; size_t row_count; if (this->lv_overlay_source != NULL) { overlay_height = vis_line_t( this->lv_overlay_source->list_overlay_count(*this)); } this->get_dimensions(height, width); wrap_width = width - (this->lv_word_wrap ? 1 : this->lv_show_scrollbar ? 1 : 0); row_count = this->get_inner_height(); row = this->lv_top; bottom = y + height; while (y < bottom) { lr.lr_start = this->lv_left; lr.lr_end = this->lv_left + wrap_width; if (this->lv_overlay_source != NULL && this->lv_overlay_source->list_value_for_overlay( *this, y - vis_line_t(this->lv_y), overlay_line)) { this->mvwattrline(this->lv_window, y, 0, overlay_line, lr); overlay_line.clear(); ++y; } else if (row < (int)row_count) { attr_line_t al; this->lv_source->listview_value_for_row(*this, row, al); do { this->mvwattrline(this->lv_window, y, 0, al, lr); if (this->lv_word_wrap) { wmove(this->lv_window, y, wrap_width); wclrtoeol(this->lv_window); } lr.lr_start += wrap_width; lr.lr_end += wrap_width; ++y; } while (this->lv_word_wrap && y < bottom && lr.lr_start < (int)al.length()); ++row; } else { wmove(this->lv_window, y, 0); wclrtoeol(this->lv_window); ++y; } } if (this->lv_show_scrollbar) { double progress = 1.0; double coverage = 1.0; double adjusted_height = (double)row_count / (double)height; vis_line_t lines; if (row_count > 0) { progress = (double)this->lv_top / (double)row_count; coverage = (double)height / (double)row_count; } y = vis_line_t(this->lv_y) + vis_line_t((int)(progress * (double)height)); lines = y + min(height, vis_line_t( (int)(coverage * (double)height))); for (int gutter_y = this->lv_y; gutter_y < (this->lv_y + height); gutter_y++) { int range_start = 0, range_end; int fg = COLOR_WHITE, bg = COLOR_BLACK, attrs; chtype ch = ACS_VLINE; if (row_count > 0) { range_start = (double)(gutter_y - this->lv_y) * adjusted_height; } range_end = range_start + adjusted_height; this->lv_gutter_source->listview_gutter_value_for_range( *this, range_start, range_end, ch, fg); if (gutter_y >= y && gutter_y <= lines) { bg = COLOR_WHITE; if (fg == bg) { fg = COLOR_BLACK; } } attrs = view_colors::ansi_color_pair(fg, bg); wattron(this->lv_window, attrs); mvwaddch(this->lv_window, gutter_y, width - 1, ch); wattroff(this->lv_window, attrs); } wmove(this->lv_window, this->lv_y + height - 1, 0); } if (this->lv_show_bottom_border) { mvwchgat(this->lv_window, this->lv_y + height - 1, 0, width - 1, A_UNDERLINE, 0, NULL); } this->lv_needs_update = false; } } static int scroll_polarity(mouse_button_t button) { return button == BUTTON_SCROLL_UP ? -1 : 1; } bool listview_curses::handle_mouse(mouse_event &me) { vis_line_t inner_height, height; struct timeval diff; unsigned long width; timersub(&me.me_time, &this->lv_mouse_time, &diff); this->get_dimensions(height, width); inner_height = this->get_inner_height(); switch (me.me_button) { case BUTTON_SCROLL_UP: case BUTTON_SCROLL_DOWN: if (diff.tv_sec > 0 || diff.tv_usec > 80000) { this->lv_scroll_accel = 1; this->lv_scroll_velo = 0; } else { this->lv_scroll_accel += 2; } this->lv_scroll_velo += this->lv_scroll_accel; this->shift_top(vis_line_t(scroll_polarity(me.me_button) * this->lv_scroll_velo), true); break; default: break; } this->lv_mouse_time = me.me_time; if (me.me_button != BUTTON_LEFT || inner_height == 0 || (this->lv_mouse_mode != LV_MODE_DRAG && me.me_x < (int)(width - 2))) { return false; } if (me.me_state == BUTTON_STATE_RELEASED) { this->lv_mouse_y = -1; this->lv_mouse_mode = LV_MODE_NONE; return true; } int scroll_top, scroll_bottom, shift_amount = 0, new_top = 0; double top_pct, bot_pct, pct; top_pct = (double)this->get_top() / (double)inner_height; bot_pct = (double)this->get_bottom() / (double)inner_height; scroll_top = (this->get_y() + (int)(top_pct * (double)height)); scroll_bottom = (this->get_y() + (int)(bot_pct * (double)height)); if (this->lv_mouse_mode == LV_MODE_NONE) { if ((scroll_top - 1) <= me.me_y && me.me_y <= (scroll_bottom + 1)) { this->lv_mouse_mode = LV_MODE_DRAG; this->lv_mouse_y = me.me_y - scroll_top; } else if (me.me_y < scroll_top) { this->lv_mouse_mode = LV_MODE_UP; } else { this->lv_mouse_mode = LV_MODE_DOWN; } } switch (this->lv_mouse_mode) { case LV_MODE_NONE: require(0); break; case LV_MODE_UP: if (me.me_y < scroll_top) { shift_amount = -1 * height; } break; case LV_MODE_DOWN: if (me.me_y > scroll_bottom) { shift_amount = height; } break; case LV_MODE_DRAG: pct = (double)inner_height / (double)height; new_top = me.me_y - this->get_y() - this->lv_mouse_y; new_top = (int)floor(((double)new_top * pct) + 0.5); this->set_top(vis_line_t(new_top)); break; } if (shift_amount != 0) { this->shift_top(vis_line_t(shift_amount)); } return true; } lnav-0.7.0/src/listview_curses.hh000664 000765 000024 00000034516 12307030336 017300 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file listview_curses.hh */ #ifndef __listview_curses_hh #define __listview_curses_hh #include #include #include #include #include "strong_int.hh" #include "view_curses.hh" /** Strongly-typed integer for visible lines. */ STRONG_INT_TYPE(int, vis_line); class listview_curses; /** * Data source for lines to be displayed by the listview_curses object. */ class list_data_source { public: virtual ~list_data_source() { }; /** @return The number of rows in the list. */ virtual size_t listview_rows(const listview_curses &lv) = 0; /** * Get the string value for a row in the list. * * @param row The row number. * @param value_out The destination for the string value. */ virtual void listview_value_for_row(const listview_curses &lv, vis_line_t row, attr_line_t &value_out) = 0; virtual size_t listview_size_for_row(const listview_curses &lv, vis_line_t row) = 0; virtual std::string listview_source_name(const listview_curses &lv) { return ""; }; }; class list_gutter_source { public: virtual ~list_gutter_source() { }; virtual void listview_gutter_value_for_range( const listview_curses &lv, int start, int end, chtype &ch_out, int &fg_out) { ch_out = ACS_VLINE; fg_out = COLOR_WHITE; }; }; struct listview_overlay { listview_overlay(int y, const attr_line_t &al) : lo_y(y), lo_line(al) { }; int get_absolute_y(int height) const { if (this->lo_y >= 0) { return this->lo_y; } return height + this->lo_y; }; int lo_y; attr_line_t lo_line; }; class list_overlay_source { public: virtual ~list_overlay_source() { }; virtual size_t list_overlay_count(const listview_curses &lv) = 0; virtual bool list_value_for_overlay(const listview_curses &lv, vis_line_t y, attr_line_t &value_out) = 0; }; /** * View that displays a list of lines that can optionally contain highlighting. */ class listview_curses : public view_curses { public: typedef view_action action; /** Construct an empty list view. */ listview_curses(); virtual ~listview_curses(); void set_title(const std::string &title) { this->lv_title = title; }; const std::string &get_title() const { return this->lv_title; }; /** @param src The data source delegate. */ void set_data_source(list_data_source *src) { this->lv_source = src; this->reload_data(); }; /** @return The data source delegate. */ list_data_source *get_data_source() const { return this->lv_source; }; void set_gutter_source(list_gutter_source *src) { this->lv_gutter_source = src; }; /** @param src The data source delegate. */ void set_overlay_source(list_overlay_source *src) { this->lv_overlay_source = src; this->reload_data(); }; /** @return The overlay source delegate. */ list_overlay_source *get_overlay_source() { return this->lv_overlay_source; }; /** * @param va The action to invoke when the view is scrolled. * @todo Allow multiple observers. */ void set_scroll_action(action va) { this->lv_scroll = va; }; template void set_scroll_action(action::mem_functor_t<_Receiver> *mf) { this->lv_scroll = action(mf); }; void set_show_scrollbar(bool ss) { this->lv_show_scrollbar = ss; }; bool get_show_scrollbar() const { return this->lv_show_scrollbar; }; void set_show_bottom_border(bool val) { this->lv_show_bottom_border = val; }; bool get_show_bottom_border() const { return this->lv_show_bottom_border; }; void set_word_wrap(bool ww) { bool scroll_down = this->lv_top >= this->get_top_for_last_row(); this->lv_word_wrap = ww; if (ww && scroll_down && this->lv_top < this->get_top_for_last_row()) { this->lv_top = this->get_top_for_last_row(); } if (ww) { this->lv_left = 0; } this->set_needs_update(); }; bool get_word_wrap() const { return this->lv_word_wrap; }; enum row_direction_t { RD_UP = -1, RD_DOWN = 1, }; vis_line_t rows_available(vis_line_t line, row_direction_t dir) { unsigned long width; vis_line_t height; vis_line_t retval(0); this->get_dimensions(height, width); if (this->lv_word_wrap) { size_t row_count = this->lv_source->listview_rows(*this); width -= 1; while ((height > 0) && (line >= 0) && ((size_t)line < row_count)) { size_t len = this->lv_source->listview_size_for_row(*this, line); do { len -= std::min((size_t)width, len); --height; } while (len > 0); line += vis_line_t(dir); if (height >= 0) { ++retval; } } } else { switch (dir) { case RD_UP: retval = std::min(height, line + vis_line_t(1)); break; case RD_DOWN: retval = std::min(height, vis_line_t(this->lv_source->listview_rows(*this) - line)); break; } } return retval; }; /** @param win The curses window this view is attached to. */ void set_window(WINDOW *win) { this->lv_window = win; }; /** @return The curses window this view is attached to. */ WINDOW *get_window() const { return this->lv_window; }; void set_y(unsigned int y) { if (y != this->lv_y) { this->lv_y = y; this->lv_needs_update = true; } }; unsigned int get_y() const { return this->lv_y; }; /** * Set the line number to be displayed at the top of the view. If the * value is invalid, flash() will be called. If the value is valid, the * new value will be set and the scroll action called. * * @param top The new value for top. * @param suppress_flash Don't call flash() if the top is out-of-bounds. */ void set_top(vis_line_t top, bool suppress_flash = false) { if (this->get_inner_height() > 0 && top >= this->get_inner_height()) { top = vis_line_t(this->get_inner_height() - 1); } if (top < 0 || (top > 0 && top >= this->get_inner_height())) { if (suppress_flash == false) { alerter::singleton().chime(); } } else if (this->lv_top != top) { this->lv_top = top; this->lv_scroll.invoke(this); this->lv_needs_update = true; } }; /** @return The line number that is displayed at the top. */ vis_line_t get_top() const { return this->lv_top; }; /** @return The line number that is displayed at the bottom. */ vis_line_t get_bottom() { vis_line_t retval = this->lv_top; retval += vis_line_t(this->rows_available(retval, RD_DOWN) - 1); return retval; }; vis_line_t get_top_for_last_row() { vis_line_t retval(0); if (this->get_inner_height() > 0) { vis_line_t last_line(this->get_inner_height() - 1); retval = last_line - vis_line_t(this->rows_available(last_line, RD_UP) - 1); if ((retval + 1) < this->get_inner_height()) { ++retval; } } return retval; }; /** @return True if the given line is visible. */ bool is_visible(vis_line_t line) { return this->get_top() <= line && line <= this->get_bottom(); }; /** * Shift the value of top by the given value. * * @param offset The amount to change top by. * @param suppress_flash Don't call flash() if the offset is out-of-bounds. * @return The final value of top. */ vis_line_t shift_top(vis_line_t offset, bool suppress_flash = false) { if (offset < 0 && this->lv_top == 0) { if (suppress_flash == false) { alerter::singleton().chime(); } } else { this->set_top(std::max(vis_line_t(0), this->lv_top + offset), suppress_flash); } return this->lv_top; }; /** * Set the column number to be displayed at the left of the view. If the * value is invalid, flash() will be called. If the value is valid, the * new value will be set and the scroll action called. * * @param left The new value for left. */ void set_left(unsigned int left) { if (this->lv_left != left) { this->lv_left = left; this->lv_scroll.invoke(this); this->lv_needs_update = true; } }; /** @return The column number that is displayed at the left. */ unsigned int get_left() const { return this->lv_left; }; /** * Shift the value of left by the given value. * * @param offset The amount to change top by. * @return The final value of top. */ unsigned int shift_left(int offset) { if (this->lv_word_wrap) { alerter::singleton().chime(); } else if (offset < 0 && this->lv_left < (unsigned int)-offset) { this->set_left(0); } else { this->set_left(this->lv_left + offset); } return this->lv_left; }; /** * Set the height of the view. A value greater than one is considered to * be an absolute size. A value less than or equal to zero makes the * height relative to the size of the enclosing window. * * @height The new height. */ void set_height(vis_line_t height) { if (this->lv_height != height) { this->lv_height = height; this->lv_needs_update = true; } }; /** @return The absolute or relative height of the window. */ vis_line_t get_height() const { return this->lv_height; }; /** @return The number of rows of data in this view's source data. */ vis_line_t get_inner_height() const { return vis_line_t(this->lv_source == NULL ? 0 : this->lv_source->listview_rows(*this)); }; void set_needs_update() { this->lv_needs_update = true; }; /** * Get the actual dimensions of the view. * * @param height_out The actual height of the view in lines. * @param width_out The actual width of the view in columns. */ void get_dimensions(vis_line_t &height_out, unsigned long &width_out) { unsigned long height; if (this->lv_window == NULL) { height_out = vis_line_t(1); width_out = 0; } else { getmaxyx(this->lv_window, height, width_out); if (this->lv_height < 1) { height_out = vis_line_t(height) + this->lv_height - vis_line_t(this->lv_y); } else { height_out = this->lv_height; } } }; /** This method should be called when the data source has changed. */ void reload_data(void); /** * @param ch The input to be handled. * @return True if the key was eaten by this view. */ bool handle_key(int ch); /** * Query the data source and draw the visible lines on the display. */ virtual void do_update(void); bool handle_mouse(mouse_event &me); protected: enum lv_mode_t { LV_MODE_NONE, LV_MODE_DOWN, LV_MODE_UP, LV_MODE_DRAG }; static list_gutter_source DEFAULT_GUTTER_SOURCE; std::string lv_title; list_data_source * lv_source; /*< The data source delegate. */ list_overlay_source *lv_overlay_source; action lv_scroll; /*< The scroll action. */ WINDOW * lv_window; /*< The window that contains this view. */ unsigned int lv_y; /*< The y offset of this view. */ vis_line_t lv_top; /*< The line at the top of the view. */ unsigned int lv_left; /*< The column at the left of the view. */ vis_line_t lv_height; /*< The abs/rel height of the view. */ bool lv_needs_update; /*< Flag to indicate if a display update * is needed. */ bool lv_show_scrollbar; /*< Draw the scrollbar in the view. */ bool lv_show_bottom_border; list_gutter_source *lv_gutter_source; bool lv_word_wrap; struct timeval lv_mouse_time; int lv_scroll_accel; int lv_scroll_velo; int lv_mouse_y; lv_mode_t lv_mouse_mode; }; #endif lnav-0.7.0/src/lnav.cc000664 000765 000024 00000423441 12313213543 014773 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file lnav.cc * * XXX This file has become a dumping ground for code and needs to be broken up * a bit. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lnav.hh" #include "help.hh" #include "init-sql.hh" #include "logfile.hh" #include "lnav_log.hh" #include "log_accel.hh" #include "lnav_util.hh" #include "ansi_scrubber.hh" #include "listview_curses.hh" #include "statusview_curses.hh" #include "vt52_curses.hh" #include "readline_curses.hh" #include "textview_curses.hh" #include "logfile_sub_source.hh" #include "textfile_sub_source.hh" #include "grep_proc.hh" #include "bookmarks.hh" #include "hist_source.hh" #include "top_status_source.hh" #include "bottom_status_source.hh" #include "piper_proc.hh" #include "log_vtab_impl.hh" #include "db_sub_source.hh" #include "pcrecpp.h" #include "termios_guard.hh" #include "data_parser.hh" #include "xterm_mouse.hh" #include "lnav_commands.hh" #include "column_namer.hh" #include "log_data_table.hh" #include "log_format_loader.hh" #include "session_data.hh" #include "lnav_config.hh" #include "sql_util.hh" #include "sqlite-extension-func.h" #include "term_extra.hh" #include "log_data_helper.hh" #include "readline_highlighters.hh" #include "yajlpp.hh" using namespace std; static multimap DEFAULT_FILES; struct _lnav_data lnav_data; struct hist_level { int hl_bucket_size; int hl_group_size; }; static struct hist_level HIST_ZOOM_VALUES[] = { { 24 * 60 * 60, 7 * 24 * 60 * 60 }, { 4 * 60 * 60, 24 * 60 * 60 }, { 60 * 60, 24 * 60 * 60 }, { 10 * 60, 60 * 60 }, { 60, 60 * 60 }, }; static const int HIST_ZOOM_LEVELS = sizeof(HIST_ZOOM_VALUES) / sizeof(struct hist_level); static bookmark_type_t BM_EXAMPLE; static bookmark_type_t BM_QUERY; const char *lnav_view_strings[LNV__MAX + 1] = { "log", "text", "help", "histogram", "graph", "db", "example", "schema", NULL }; static const char *view_titles[LNV__MAX] = { "LOG", "TEXT", "HELP", "HIST", "GRAPH", "DB", "EXAMPLE", "SCHEMA", }; static bool rescan_files(bool required = false); class log_gutter_source : public list_gutter_source { public: void listview_gutter_value_for_range( const listview_curses &lv, int start, int end, chtype &ch, int &fg_out) { textview_curses *tc = (textview_curses *)&lv; vis_bookmarks &bm = tc->get_bookmarks(); vis_line_t next; bool search_hit = false; start -= 1; next = bm[&textview_curses::BM_SEARCH].next(vis_line_t(start)); search_hit = (next != -1 && next <= end); next = bm[&BM_QUERY].next(vis_line_t(start)); search_hit = search_hit || (next != -1 && next <= end); next = bm[&textview_curses::BM_USER].next(vis_line_t(start)); if (next == -1) { next = bm[&textview_curses::BM_PARTITION].next(vis_line_t(start)); } if (next != -1 && next <= end) { ch = search_hit ? ACS_PLUS : ACS_LTEE; } else { ch = search_hit ? ACS_RTEE : ACS_VLINE; } next = bm[&logfile_sub_source::BM_ERRORS].next(vis_line_t(start)); if (next != -1 && next <= end) { fg_out = COLOR_RED; } else { next = bm[&logfile_sub_source::BM_WARNINGS].next(vis_line_t(start)); if (next != -1 && next <= end) { fg_out = COLOR_YELLOW; } } }; }; class field_overlay_source : public list_overlay_source { public: field_overlay_source(logfile_sub_source &lss) : fos_active(false), fos_active_prev(false), fos_log_helper(lss) { }; size_t list_overlay_count(const listview_curses &lv) { logfile_sub_source &lss = lnav_data.ld_log_source; if (!this->fos_active) { return 0; } if (lss.text_line_count() == 0) { this->fos_log_helper.clear(); return 0; } content_line_t cl = lss.at(lv.get_top()); if (!this->fos_log_helper.parse_line(cl)) { return 0; } this->fos_key_size = 0; for (std::vector::iterator iter = this->fos_log_helper.ldh_line_values.begin(); iter != this->fos_log_helper.ldh_line_values.end(); ++iter) { this->fos_key_size = max(this->fos_key_size, (int)iter->lv_name.length()); } for (data_parser::element_list_t::iterator iter = this->fos_log_helper.ldh_parser->dp_pairs.begin(); iter != this->fos_log_helper.ldh_parser->dp_pairs.end(); ++iter) { std::string colname = this->fos_log_helper.ldh_parser->get_element_string( iter->e_sub_elements->front()); colname = this->fos_log_helper.ldh_namer->add_column(colname); this->fos_key_size = max(this->fos_key_size, (int)colname.length()); } return 1 + 1 + this->fos_log_helper.ldh_line_values.size() + 1 + this->fos_log_helper.ldh_parser->dp_pairs.size(); }; bool list_value_for_overlay(const listview_curses &lv, vis_line_t y, attr_line_t &value_out) { view_colors &vc = view_colors::singleton(); if (!this->fos_active || this->fos_log_helper.ldh_parser.get() == NULL) { return false; } size_t total_count = (1 + 1 + this->fos_log_helper.ldh_line_values.size() + 1 + this->fos_log_helper.ldh_parser->dp_pairs.size()); int row = (int)y - 1; bool last_line = (row == (int)(total_count - 1)); if (row < 0 || row >= (int)total_count) { return false; } std::string &str = value_out.get_string(); if (row == 0) { char old_timestamp[64], curr_timestamp[64]; struct timeval curr_tv, offset_tv, orig_tv; char log_time[256]; sql_strftime(curr_timestamp, sizeof(curr_timestamp), this->fos_log_helper.ldh_line->get_time(), this->fos_log_helper.ldh_line->get_millis(), 'T'); curr_tv = this->fos_log_helper.ldh_line->get_timeval(); offset_tv = this->fos_log_helper.ldh_file->get_time_offset(); timersub(&curr_tv, &offset_tv, &orig_tv); sql_strftime(old_timestamp, sizeof(old_timestamp), orig_tv.tv_sec, orig_tv.tv_usec / 1000, 'T'); snprintf(log_time, sizeof(log_time), " Current Time: %s Original Time: %s Offset: %+d.%03d", curr_timestamp, old_timestamp, (int)offset_tv.tv_sec, offset_tv.tv_usec / 1000); str = log_time; return true; } row -= 1; if (row == 0) { if (this->fos_log_helper.ldh_line_values.empty()) { str = " No known message fields"; } else{ str = " Known message fields:"; } return true; } row -= 1; if (row == (int)this->fos_log_helper.ldh_line_values.size()) { if (this->fos_log_helper.ldh_parser->dp_pairs.empty()) { str = " No discovered message fields"; } else{ str = " Discovered message fields:"; } return true; } if (row < (int)this->fos_log_helper.ldh_line_values.size()) { string &name = this->fos_log_helper.ldh_line_values[row].lv_name; str = " " + name; int padding = this->fos_key_size - str.length() + 3; value_out.get_attrs().push_back(string_attr( line_range(3, 3 + name.length()), &view_curses::VC_STYLE, vc.attrs_for_ident(name))); str.append(padding, ' '); str += " = " + this->fos_log_helper.ldh_line_values[row].to_string(); } else { data_parser::element_list_t::iterator iter; row -= this->fos_log_helper.ldh_line_values.size() + 1; iter = this->fos_log_helper.ldh_parser->dp_pairs.begin(); std::advance(iter, row); string &name = this->fos_log_helper.ldh_namer->cn_names[row]; str = " " + name; int padding = this->fos_key_size - str.length() + 3; value_out.get_attrs().push_back(string_attr( line_range(3, 3 + name.length()), &view_curses::VC_STYLE, vc.attrs_for_ident(name))); str.append(padding, ' '); str += " = " + this->fos_log_helper.ldh_parser->get_element_string( iter->e_sub_elements->back()); } string_attrs_t & sa = value_out.get_attrs(); struct line_range lr(1, 2); sa.push_back(string_attr(lr, &view_curses::VC_GRAPHIC, last_line ? ACS_LLCORNER : ACS_LTEE)); lr.lr_start = 3 + this->fos_key_size + 3; lr.lr_end = -1; sa.push_back(string_attr(lr, &view_curses::VC_STYLE, A_BOLD)); return true; }; bool fos_active; bool fos_active_prev; log_data_helper fos_log_helper; int fos_key_size; }; static int handle_collation_list(void *ptr, int ncols, char **colvalues, char **colnames) { if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->add_possibility(LNM_SQL, "*", colvalues[1]); } return 0; } static int handle_db_list(void *ptr, int ncols, char **colvalues, char **colnames) { if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->add_possibility(LNM_SQL, "*", colvalues[1]); } return 0; } static int handle_table_list(void *ptr, int ncols, char **colvalues, char **colnames) { if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->add_possibility(LNM_SQL, "*", colvalues[0]); } return 0; } static int handle_table_info(void *ptr, int ncols, char **colvalues, char **colnames) { if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->add_possibility(LNM_SQL, "*", colvalues[1]); } if (strcmp(colvalues[5], "1") == 0) { lnav_data.ld_db_key_names.push_back(colvalues[1]); } return 0; } static int handle_foreign_key_list(void *ptr, int ncols, char **colvalues, char **colnames) { lnav_data.ld_db_key_names.push_back(colvalues[3]); lnav_data.ld_db_key_names.push_back(colvalues[4]); return 0; } struct sqlite_metadata_callbacks lnav_sql_meta_callbacks = { handle_collation_list, handle_db_list, handle_table_list, handle_table_info, handle_foreign_key_list, }; static void add_text_possibilities(int context, const std::string &str) { static pcrecpp::RE re_escape("([.\\^$*+?()\\[\\]{}\\\\|])"); static pcrecpp::RE re_escape_no_dot("([\\^$*+?()\\[\\]{}\\\\|])"); readline_curses *rlc = lnav_data.ld_rl_view; pcre_context_static<30> pc; data_scanner ds(str); data_token_t dt; while (ds.tokenize(pc, dt)) { if (pc[0]->length() < 4) { continue; } switch (dt) { case DT_DATE: case DT_TIME: case DT_WHITE: continue; default: break; } switch (context) { case LNM_SEARCH: { string token_value, token_value_no_dot; token_value_no_dot = token_value = ds.get_input().get_substr(pc.all()); re_escape.GlobalReplace("\\\\\\1", &token_value); re_escape_no_dot.GlobalReplace("\\\\\\1", &token_value_no_dot); rlc->add_possibility(context, "*", token_value); if (token_value != token_value_no_dot) { rlc->add_possibility(context, "*", token_value_no_dot); } break; } case LNM_SQL: { string token_value = ds.get_input().get_substr(pc.all()); auto_mem quoted_token; quoted_token = sqlite3_mprintf("%Q", token_value.c_str()); rlc->add_possibility(context, "*", std::string(quoted_token)); break; } } switch (dt) { case DT_QUOTED_STRING: add_text_possibilities(context, ds.get_input().get_substr(pc[0])); break; default: break; } } } static void add_view_text_possibilities(int context, textview_curses *tc) { text_sub_source *tss = tc->get_sub_source(); readline_curses *rlc = lnav_data.ld_rl_view; rlc->clear_possibilities(context, "*"); for (vis_line_t curr_line = tc->get_top(); curr_line < tc->get_bottom(); ++curr_line) { string line; tss->text_value_for_line(*tc, curr_line, line); add_text_possibilities(context, line); } } bool setup_logline_table() { // Hidden columns don't show up in the table_info pragma. static const char *hidden_table_columns[] = { "log_path", "log_text", NULL }; static const char *commands[] = { ".schema", NULL }; textview_curses &log_view = lnav_data.ld_views[LNV_LOG]; bool retval = false; if (log_view.get_inner_height()) { vis_line_t vl = log_view.get_top(); content_line_t cl = lnav_data.ld_log_source.at_base(vl); lnav_data.ld_vtab_manager->unregister_vtab("logline"); lnav_data.ld_vtab_manager->register_vtab(new log_data_table(cl)); retval = true; } lnav_data.ld_db_key_names.clear(); if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->clear_possibilities(LNM_SQL, "*"); add_view_text_possibilities(LNM_SQL, &log_view); lnav_data.ld_rl_view->add_possibility(LNM_SQL, "*", sql_keywords); lnav_data.ld_rl_view->add_possibility(LNM_SQL, "*", sql_function_names); lnav_data.ld_rl_view->add_possibility(LNM_SQL, "*", hidden_table_columns); lnav_data.ld_rl_view->add_possibility(LNM_SQL, "*", commands); for (int lpc = 0; sqlite_registration_funcs[lpc]; lpc++) { const struct FuncDef *basic_funcs; const struct FuncDefAgg *agg_funcs; sqlite_registration_funcs[lpc](&basic_funcs, &agg_funcs); for (int lpc2 = 0; basic_funcs && basic_funcs[lpc2].zName; lpc2++) { lnav_data.ld_rl_view->add_possibility(LNM_SQL, "*", basic_funcs[lpc2].zName); } for (int lpc2 = 0; agg_funcs && agg_funcs[lpc2].zName; lpc2++) { lnav_data.ld_rl_view->add_possibility(LNM_SQL, "*", agg_funcs[lpc2].zName); } } } walk_sqlite_metadata(lnav_data.ld_db.in(), lnav_sql_meta_callbacks); { log_vtab_manager::iterator iter; for (iter = lnav_data.ld_vtab_manager->begin(); iter != lnav_data.ld_vtab_manager->end(); ++iter) { iter->second->get_foreign_keys(lnav_data.ld_db_key_names); } } stable_sort(lnav_data.ld_db_key_names.begin(), lnav_data.ld_db_key_names.end()); return retval; } /** * Observer for loading progress that updates the bottom status bar. */ class loading_observer : public logfile_sub_source::observer { public: loading_observer() : lo_last_offset(0), lo_last_line(0) { }; void logfile_indexing(logfile &lf, off_t off, size_t total) { static sig_atomic_t index_counter = 0; if (lnav_data.ld_flags & LNF_HEADLESS) { return; } /* XXX require(off <= total); */ if (off > (off_t)total) { off = total; } if ((((size_t)off == total) && (this->lo_last_offset != off)) || ui_periodic_timer::singleton().time_to_update(index_counter)) { lnav_data.ld_bottom_source.update_loading(off, total); this->do_update(); this->lo_last_offset = off; } if (!lnav_data.ld_looping) { throw logfile::error(lf.get_filename(), EINTR); } }; void logfile_sub_source_filtering(logfile_sub_source &lss, vis_line_t cl, size_t total) { static sig_atomic_t filter_counter = 0; if (lnav_data.ld_flags & LNF_HEADLESS) { return; } if ((size_t)cl == (total - 1) || ui_periodic_timer::singleton().time_to_update(filter_counter)) { lnav_data.ld_bottom_source.update_loading(cl, (total - 1)); this->do_update(); this->lo_last_line = cl; } if (!lnav_data.ld_looping) { throw logfile::error("", EINTR); } }; private: void do_update(void) { lnav_data.ld_top_source.update_time(); lnav_data.ld_status[LNS_TOP].do_update(); lnav_data.ld_status[LNS_BOTTOM].do_update(); refresh(); }; off_t lo_last_offset; vis_line_t lo_last_line; }; static void rebuild_hist(size_t old_count, bool force) { textview_curses & hist_view = lnav_data.ld_views[LNV_HISTOGRAM]; logfile_sub_source &lss = lnav_data.ld_log_source; size_t new_count = lss.text_line_count(); hist_source &hs = lnav_data.ld_hist_source; int zoom_level = lnav_data.ld_hist_zoom; time_t old_time; int lpc; old_time = hs.value_for_row(hist_view.get_top()); hs.set_bucket_size(HIST_ZOOM_VALUES[zoom_level].hl_bucket_size); hs.set_group_size(HIST_ZOOM_VALUES[zoom_level].hl_group_size); if (force) { hs.clear(); } for (lpc = old_count; lpc < (int)new_count; lpc++) { logline *ll = lss.find_line(lss.at(vis_line_t(lpc))); if (!(ll->get_level() & logline::LEVEL_CONTINUED)) { hs.add_value(ll->get_time(), bucket_type_t(ll->get_level() & ~logline::LEVEL__FLAGS)); } } hist_view.reload_data(); hist_view.set_top(hs.row_for_value(old_time)); } void rebuild_indexes(bool force) { static loading_observer obs; logfile_sub_source &lss = lnav_data.ld_log_source; textview_curses & log_view = lnav_data.ld_views[LNV_LOG]; textview_curses & text_view = lnav_data.ld_views[LNV_TEXT]; vis_line_t old_bottom(0); content_line_t top_content = content_line_t(-1); bool scroll_down; size_t old_count; time_t old_time; old_count = lss.text_line_count(); if (old_count) { top_content = lss.at(log_view.get_top()); } { textfile_sub_source * tss = &lnav_data.ld_text_source; std::list::iterator iter; logfile *front_file = NULL; int front_top = -1; bool new_data = false; old_bottom = text_view.get_top_for_last_row(); scroll_down = (text_view.get_top() >= old_bottom && !(lnav_data.ld_flags & LNF_HEADLESS)); for (iter = tss->tss_files.begin(); iter != tss->tss_files.end(); ) { try { bool new_text_data = (*iter)->rebuild_index(&obs); if ((*iter)->get_format() != NULL) { logfile *lf = *iter; if (lnav_data.ld_log_source.insert_file(lf)) { iter = tss->tss_files.erase(iter); force = true; } else { ++iter; } } else { new_data = new_data || new_text_data; if (!lnav_data.ld_files_to_front.empty() && lnav_data.ld_files_to_front.front().first == (*iter)->get_filename()) { front_file = *iter; front_top = lnav_data.ld_files_to_front.front().second; lnav_data.ld_files_to_front.pop_front(); } ++iter; } } catch (const line_buffer::error &e) { // TODO: log that we dropped this file. iter = tss->tss_files.erase(iter); } } if (front_file != NULL) { ensure_view(&text_view); if (tss->current_file() != front_file) { tss->tss_files.remove(front_file); tss->tss_files.push_front(front_file); redo_search(LNV_TEXT); text_view.reload_data(); old_bottom = vis_line_t(-1); new_data = false; } if (front_top < 0) { front_top += text_view.get_inner_height(); } if (front_top < text_view.get_inner_height()) { text_view.set_top(vis_line_t(front_top)); scroll_down = false; } } if (new_data && lnav_data.ld_search_child[LNV_TEXT].get() != NULL) { lnav_data.ld_search_child[LNV_TEXT]->get_grep_proc()->reset(); lnav_data.ld_search_child[LNV_TEXT]->get_grep_proc()-> queue_request(grep_line_t(-1)); lnav_data.ld_search_child[LNV_TEXT]->get_grep_proc()->start(); } text_view.reload_data(); if (scroll_down && text_view.get_top_for_last_row() > text_view.get_top()) { text_view.set_top(text_view.get_top_for_last_row()); } } old_time = lnav_data.ld_top_time; old_bottom = log_view.get_top_for_last_row(); scroll_down = (log_view.get_top() >= old_bottom && !(lnav_data.ld_flags & LNF_HEADLESS)); if (force) { old_count = 0; } if (lss.rebuild_index(&obs, force)) { size_t new_count = lss.text_line_count(); grep_line_t start_line; int lpc; log_view.reload_data(); if (scroll_down && log_view.get_top_for_last_row() > log_view.get_top()) { log_view.set_top(log_view.get_top_for_last_row()); } else if (!scroll_down && force) { content_line_t new_top_content = content_line_t(-1); if (new_count) { new_top_content = lss.at(log_view.get_top()); } if (new_top_content != top_content) { log_view.set_top(lss.find_from_time(old_time)); } } rebuild_hist(old_count, force); start_line = force ? grep_line_t(0) : grep_line_t(-1); if (force) { if (lnav_data.ld_search_child[LNV_LOG].get() != NULL) { lnav_data.ld_search_child[LNV_LOG]->get_grep_proc()->invalidate(); } log_view.match_reset(); } for (lpc = 0; lpc < LG__MAX; lpc++) { if (lnav_data.ld_grep_child[lpc].get() != NULL) { lnav_data.ld_grep_child[lpc]->get_grep_proc()-> queue_request(start_line); lnav_data.ld_grep_child[lpc]->get_grep_proc()->start(); } } if (lnav_data.ld_search_child[LNV_LOG].get() != NULL) { lnav_data.ld_search_child[LNV_LOG]->get_grep_proc()->reset(); lnav_data.ld_search_child[LNV_LOG]->get_grep_proc()-> queue_request(start_line); lnav_data.ld_search_child[LNV_LOG]->get_grep_proc()->start(); } } lnav_data.ld_bottom_source.update_filtered(lss); lnav_data.ld_scroll_broadcaster.invoke(lnav_data.ld_view_stack.top()); } class plain_text_source : public text_sub_source { public: plain_text_source(string text) { size_t start = 0, end; while ((end = text.find('\n', start)) != string::npos) { this->tds_lines.push_back(text.substr(start, end - start)); start = end + 1; } if (start < text.length()) { this->tds_lines.push_back(text.substr(start)); } }; plain_text_source(const vector &lines) { this->tds_lines = lines; }; size_t text_line_count() { return this->tds_lines.size(); }; void text_value_for_line(textview_curses &tc, int row, string &value_out, bool no_scrub) { value_out = this->tds_lines[row]; }; size_t text_size_for_line(textview_curses &tc, int row, bool raw) { return this->tds_lines[row].length(); }; private: vector tds_lines; }; class time_label_source : public hist_source::label_source { public: time_label_source() { }; void hist_label_for_bucket(int bucket_start_value, const hist_source::bucket_t &bucket, string &label_out) { hist_source::bucket_t::const_iterator iter; int total = 0, errors = 0, warnings = 0; time_t bucket_time = bucket_start_value; struct tm *bucket_tm; char buffer[128]; int len; bucket_tm = gmtime((time_t *)&bucket_time); if (bucket_tm) { strftime(buffer, sizeof(buffer), " %a %b %d %H:%M ", bucket_tm); } else { log_error("bad time %d", bucket_start_value); buffer[0] = '\0'; } for (iter = bucket.begin(); iter != bucket.end(); iter++) { total += (int)iter->second; switch (iter->first) { case logline::LEVEL_FATAL: case logline::LEVEL_ERROR: case logline::LEVEL_CRITICAL: errors += (int)iter->second; break; case logline::LEVEL_WARNING: warnings += (int)iter->second; break; } } len = strlen(buffer); snprintf(&buffer[len], sizeof(buffer) - len, " %8d total %8d errors %8d warnings", total, errors, warnings); label_out = string(buffer); }; }; static bool append_default_files(lnav_flags_t flag) { bool retval = true; if (lnav_data.ld_flags & flag) { pair::iterator, multimap::iterator> range; for (range = DEFAULT_FILES.equal_range(flag); range.first != range.second; range.first++) { string path = range.first->second; struct stat st; if (access(path.c_str(), R_OK) == 0) { auto_mem abspath; path = get_current_dir() + range.first->second; if ((abspath = realpath(path.c_str(), NULL)) == NULL) { perror("Unable to resolve path"); } else { lnav_data.ld_file_names.insert(make_pair(abspath.in(), -1)); } } else if (stat(path.c_str(), &st) == 0) { fprintf(stderr, "error: cannot read -- %s%s\n", get_current_dir().c_str(), path.c_str()); retval = false; } } } return retval; } static void sigint(int sig) { lnav_data.ld_looping = false; } static void sigwinch(int sig) { lnav_data.ld_winched = true; } static void sigchld(int sig) { lnav_data.ld_child_terminated = true; } static void back_ten(int ten_minute) { textview_curses * tc = lnav_data.ld_view_stack.top(); logfile_sub_source *lss; lss = dynamic_cast(tc->get_sub_source()); if (!lss) return; time_t hour = rounddown_offset(lnav_data.ld_top_time, 60 * 60, ten_minute * 10 * 60); vis_line_t line = lss->find_from_time(hour); --line; lnav_data.ld_view_stack.top()->set_top(line); } static void update_view_name(void) { status_field &sf = lnav_data.ld_top_source.statusview_value_for_field( top_status_source::TSF_VIEW_NAME); textview_curses * tc = lnav_data.ld_view_stack.top(); struct line_range lr(0); sf.set_value("% 5s ", tc->get_title().c_str()); sf.get_value().get_attrs().push_back( string_attr(lr, &view_curses::VC_STYLE, A_REVERSE | view_colors::ansi_color_pair(COLOR_BLUE, COLOR_WHITE))); } bool toggle_view(textview_curses *toggle_tc) { textview_curses *tc = lnav_data.ld_view_stack.top(); bool retval = false; if (tc == toggle_tc) { lnav_data.ld_view_stack.pop(); } else { lnav_data.ld_view_stack.push(toggle_tc); retval = true; } tc = lnav_data.ld_view_stack.top(); tc->set_needs_update(); lnav_data.ld_scroll_broadcaster.invoke(tc); update_view_name(); return retval; } void redo_search(lnav_view_t view_index) { textview_curses *tc = &lnav_data.ld_views[view_index]; tc->reload_data(); if (lnav_data.ld_search_child[view_index].get() != NULL) { grep_proc *gp = lnav_data.ld_search_child[view_index]->get_grep_proc(); tc->match_reset(); gp->reset(); gp->queue_request(grep_line_t(0)); gp->start(); } lnav_data.ld_scroll_broadcaster.invoke(tc); } static void open_schema_view(void) { textview_curses *schema_tc = &lnav_data.ld_views[LNV_SCHEMA]; string schema; dump_sqlite_schema(lnav_data.ld_db, schema); schema += "\n\n-- Virtual Table Definitions --\n\n"; for (log_vtab_manager::iterator vtab_iter = lnav_data.ld_vtab_manager->begin(); vtab_iter != lnav_data.ld_vtab_manager->end(); ++vtab_iter) { schema += vtab_iter->second->get_table_statement(); } if (schema_tc->get_sub_source() != NULL) { delete schema_tc->get_sub_source(); } schema_tc->set_sub_source(new plain_text_source(schema)); } /** * Ensure that the view is on the top of the view stack. * * @param expected_tc The text view that should be on top. */ void ensure_view(textview_curses *expected_tc) { textview_curses *tc = lnav_data.ld_view_stack.top(); if (tc != expected_tc) { if (expected_tc == &lnav_data.ld_views[LNV_SCHEMA]) { open_schema_view(); } toggle_view(expected_tc); } } static vis_line_t next_cluster( vis_line_t(bookmark_vector::*f) (vis_line_t), bookmark_type_t *bt, vis_line_t top) { textview_curses *tc = lnav_data.ld_view_stack.top(); vis_bookmarks &bm = tc->get_bookmarks(); vis_line_t last_top(top); while ((top = (bm[bt].*f)(top)) != -1) { int diff = top - last_top; if (diff > 1) { return top; } else if (diff < -1) { last_top = top; while ((top = (bm[bt].*f)(top)) != -1) { if (std::abs(last_top - top) > 1) break; last_top = top; } return last_top; } last_top = top; } return vis_line_t(-1); } static bool moveto_cluster(vis_line_t(bookmark_vector::*f) ( vis_line_t), bookmark_type_t *bt, vis_line_t top) { textview_curses *tc = lnav_data.ld_view_stack.top(); vis_line_t new_top; new_top = next_cluster(f, bt, top); if (new_top != -1) { tc->set_top(new_top); return true; } alerter::singleton().chime(); return false; } static void check_for_clipboard(FILE **pfile, const char *execstr) { if (execstr == NULL || pfile == NULL || *pfile != NULL) { return; } if ((*pfile = popen(execstr, "w")) != NULL && pclose(*pfile) == 0) { *pfile = popen(execstr, "w"); } else { *pfile = NULL; } return; } /* XXX For one, this code is kinda crappy. For two, we should probably link * directly with X so we don't need to have xclip installed and it'll work if * we're ssh'd into a box. */ static void copy_to_xclip(void) { textview_curses *tc = lnav_data.ld_view_stack.top(); bookmark_vector &bv = tc->get_bookmarks()[&textview_curses::BM_USER]; bookmark_vector::iterator iter; FILE * pfile = NULL; int line_count = 0; string line; /* XXX : Check if this is linux or MAC. Probably not the best solution but */ /* better than traversing the PATH to stat for the binaries or trying to */ /* forkexec. */ check_for_clipboard(&pfile, "xclip -i > /dev/null 2>&1"); check_for_clipboard(&pfile, "pbcopy > /dev/null 2>&1"); if (!pfile) { flash(); lnav_data.ld_rl_view->set_value( "error: Unable to copy to clipboard. " "Make sure xclip or pbcopy is installed."); return; } for (iter = bv.begin(); iter != bv.end(); iter++) { tc->grep_value_for_line(*iter, line); fprintf(pfile, "%s\n", line.c_str()); line_count += 1; } pclose(pfile); pfile = NULL; char buffer[128]; snprintf(buffer, sizeof(buffer), "Copied " ANSI_BOLD("%d") " lines to the clipboard", line_count); lnav_data.ld_rl_view->set_value(buffer); } static void handle_paging_key(int ch) { textview_curses * tc = lnav_data.ld_view_stack.top(); logfile_sub_source *lss = NULL; vis_bookmarks & bm = tc->get_bookmarks(); if (tc->handle_key(ch)) { return; } lss = dynamic_cast(tc->get_sub_source()); /* process the command keystroke */ switch (ch) { case 'q': case 'Q': { string msg = ""; if (tc == &lnav_data.ld_views[LNV_DB]) { msg = HELP_MSG_2(v, V, "to switch to the SQL result view"); } else if (tc == &lnav_data.ld_views[LNV_HISTOGRAM]) { msg = HELP_MSG_2(i, I, "to switch to the histogram view"); } else if (tc == &lnav_data.ld_views[LNV_TEXT]) { msg = HELP_MSG_1(t, "to switch to the text file view"); } else if (tc == &lnav_data.ld_views[LNV_GRAPH]) { msg = HELP_MSG_1(g, "to switch to the graph view"); } lnav_data.ld_rl_view->set_alt_value(msg); } lnav_data.ld_view_stack.pop(); if (lnav_data.ld_view_stack.empty() || (lnav_data.ld_view_stack.size() == 1 && lnav_data.ld_log_source.text_line_count() == 0)) { lnav_data.ld_looping = false; } else { tc = lnav_data.ld_view_stack.top(); tc->set_needs_update(); lnav_data.ld_scroll_broadcaster.invoke(tc); update_view_name(); } break; case KEY_F(2): if (xterm_mouse::is_available()) { lnav_data.ld_mouse.set_enabled(!lnav_data.ld_mouse.is_enabled()); } else { lnav_data.ld_rl_view->set_value( "error: mouse support is not available, make sure your TERM is set to " "xterm or xterm-256color"); } break; case 'c': copy_to_xclip(); break; case 'C': if (lss) { lss->get_user_bookmarks()[&textview_curses::BM_USER].clear(); } tc->get_bookmarks()[&textview_curses::BM_USER].clear(); tc->reload_data(); lnav_data.ld_rl_view->set_value("Cleared bookmarks"); break; case 'e': moveto_cluster(&bookmark_vector::next, &logfile_sub_source::BM_ERRORS, tc->get_top()); lnav_data.ld_rl_view->set_alt_value(HELP_MSG_2( w, W, "to move forward/backward through warning messages")); break; case 'E': moveto_cluster(&bookmark_vector::prev, &logfile_sub_source::BM_ERRORS, tc->get_top()); lnav_data.ld_rl_view->set_alt_value(HELP_MSG_2( w, W, "to move forward/backward through warning messages")); break; case 'w': moveto_cluster(&bookmark_vector::next, &logfile_sub_source::BM_WARNINGS, tc->get_top()); lnav_data.ld_rl_view->set_alt_value(HELP_MSG_2( o, O, "to move forward/backward an hour")); break; case 'W': moveto_cluster(&bookmark_vector::prev, &logfile_sub_source::BM_WARNINGS, tc->get_top()); lnav_data.ld_rl_view->set_alt_value(HELP_MSG_2( o, O, "to move forward/backward an hour")); break; case 'n': tc->set_top(bm[&textview_curses::BM_SEARCH].next(tc->get_top())); lnav_data.ld_bottom_source.grep_error(""); lnav_data.ld_rl_view->set_alt_value( "Press '" ANSI_BOLD(">") "' or '" ANSI_BOLD("<") "' to scroll horizontally to a search result"); break; case 'N': tc->set_top(bm[&textview_curses::BM_SEARCH].prev(tc->get_top())); lnav_data.ld_bottom_source.grep_error(""); lnav_data.ld_rl_view->set_alt_value( "Press '" ANSI_BOLD(">") "' or '" ANSI_BOLD("<") "' to scroll horizontally to a search result"); break; case 'y': tc->set_top(bm[&BM_QUERY].next(tc->get_top())); break; case 'Y': tc->set_top(bm[&BM_QUERY].prev(tc->get_top())); break; case '>': { std::pair range; tc->horiz_shift(tc->get_top(), tc->get_bottom(), tc->get_left(), "$search", range); if (range.second != INT_MAX) { tc->set_left(range.second); lnav_data.ld_rl_view->set_alt_value( HELP_MSG_1(m, "to bookmark a line")); } else{ flash(); } } break; case '<': if (tc->get_left() == 0) { flash(); } else { std::pair range; tc->horiz_shift(tc->get_top(), tc->get_bottom(), tc->get_left(), "$search", range); if (range.first != -1) { tc->set_left(range.first); } else{ tc->set_left(0); } lnav_data.ld_rl_view->set_alt_value( HELP_MSG_1(m, "to bookmark a line")); } break; case 'f': if (tc == &lnav_data.ld_views[LNV_LOG]) { tc->set_top(bm[&logfile_sub_source::BM_FILES].next(tc->get_top())); } else if (tc == &lnav_data.ld_views[LNV_TEXT]) { textfile_sub_source &tss = lnav_data.ld_text_source; if (!tss.tss_files.empty()) { tss.tss_files.push_front(tss.tss_files.back()); tss.tss_files.pop_back(); redo_search(LNV_TEXT); } } break; case 'F': if (tc == &lnav_data.ld_views[LNV_LOG]) { tc->set_top(bm[&logfile_sub_source::BM_FILES].prev(tc->get_top())); } else if (tc == &lnav_data.ld_views[LNV_TEXT]) { textfile_sub_source &tss = lnav_data.ld_text_source; if (!tss.tss_files.empty()) { tss.tss_files.push_back(tss.tss_files.front()); tss.tss_files.pop_front(); redo_search(LNV_TEXT); } } break; case 'z': if (tc == &lnav_data.ld_views[LNV_HISTOGRAM]) { if ((lnav_data.ld_hist_zoom + 1) >= HIST_ZOOM_LEVELS) { flash(); } else { lnav_data.ld_hist_zoom += 1; rebuild_hist(0, true); } lnav_data.ld_rl_view->set_alt_value(HELP_MSG_1( I, "to switch to the log view at the top displayed time")); } break; case 'Z': if (tc == &lnav_data.ld_views[LNV_HISTOGRAM]) { if (lnav_data.ld_hist_zoom == 0) { flash(); } else { lnav_data.ld_hist_zoom -= 1; rebuild_hist(0, true); } lnav_data.ld_rl_view->set_alt_value(HELP_MSG_1( I, "to switch to the log view at the top displayed time")); } break; case 'u': { vis_line_t user_top, part_top; lnav_data.ld_rl_view->set_alt_value( HELP_MSG_1(c, "to copy marked lines to the clipboard; ") HELP_MSG_1(C, "to clear marked lines")); user_top = next_cluster(&bookmark_vector::next, &textview_curses::BM_USER, tc->get_top()); part_top = next_cluster(&bookmark_vector::next, &textview_curses::BM_PARTITION, tc->get_top()); if (part_top == -1 && user_top == -1) { alerter::singleton().chime(); } else if (part_top == -1) { tc->set_top(user_top); } else if (user_top == -1) { tc->set_top(part_top); } else { tc->set_top(min(user_top, part_top)); } break; } case 'U': { vis_line_t user_top, part_top; user_top = next_cluster(&bookmark_vector::prev, &textview_curses::BM_USER, tc->get_top()); part_top = next_cluster(&bookmark_vector::prev, &textview_curses::BM_PARTITION, tc->get_top()); if (part_top == -1 && user_top == -1) { alerter::singleton().chime(); } else if (part_top == -1) { tc->set_top(user_top); } else if (user_top == -1) { tc->set_top(part_top); } else { tc->set_top(max(user_top, part_top)); } break; } case 'm': lnav_data.ld_last_user_mark[tc] = tc->get_top(); tc->toggle_user_mark(&textview_curses::BM_USER, vis_line_t(lnav_data.ld_last_user_mark[tc])); tc->reload_data(); lnav_data.ld_rl_view->set_alt_value(HELP_MSG_2( u, U, "to move forward/backward through user bookmarks")); break; case 'J': if (lnav_data.ld_last_user_mark.find(tc) == lnav_data.ld_last_user_mark.end() || !tc->is_visible(vis_line_t(lnav_data.ld_last_user_mark[tc]))) { lnav_data.ld_last_user_mark[tc] = tc->get_top(); } else { vis_line_t height; unsigned long width; tc->get_dimensions(height, width); if (lnav_data.ld_last_user_mark[tc] > tc->get_bottom() - 2 && tc->get_top() + height < tc->get_inner_height()) { tc->shift_top(vis_line_t(1)); } if (lnav_data.ld_last_user_mark[tc] + 1 >= tc->get_inner_height()) { break; } lnav_data.ld_last_user_mark[tc] += 1; } tc->toggle_user_mark(&textview_curses::BM_USER, vis_line_t(lnav_data.ld_last_user_mark[tc])); tc->reload_data(); lnav_data.ld_rl_view->set_alt_value(HELP_MSG_1( c, "to copy marked lines to the clipboard")); break; case 'K': { int new_mark; if (lnav_data.ld_last_user_mark.find(tc) == lnav_data.ld_last_user_mark.end() || !tc->is_visible(vis_line_t(lnav_data.ld_last_user_mark[tc]))) { lnav_data.ld_last_user_mark[tc] = -1; new_mark = tc->get_top(); } else { new_mark = lnav_data.ld_last_user_mark[tc]; } tc->toggle_user_mark(&textview_curses::BM_USER, vis_line_t(new_mark)); if (new_mark == tc->get_top()) { tc->shift_top(vis_line_t(-1)); } if (new_mark > 0) { lnav_data.ld_last_user_mark[tc] = new_mark - 1; } else { lnav_data.ld_last_user_mark[tc] = new_mark; flash(); } tc->reload_data(); lnav_data.ld_rl_view->set_alt_value(HELP_MSG_1( c, "to copy marked lines to the clipboard")); } break; case 'M': if (lnav_data.ld_last_user_mark.find(tc) == lnav_data.ld_last_user_mark.end()) { flash(); } else { int start_line = min((int)tc->get_top(), lnav_data.ld_last_user_mark[tc] + 1); int end_line = max((int)tc->get_top(), lnav_data.ld_last_user_mark[tc] - 1); tc->toggle_user_mark(&textview_curses::BM_USER, vis_line_t(start_line), vis_line_t(end_line)); tc->reload_data(); } break; #if 0 case 'S': { bookmark_vector::iterator iter; for (iter = bm[&textview_curses::BM_SEARCH].begin(); iter != bm[&textview_curses::BM_SEARCH].end(); ++iter) { tc->toggle_user_mark(&textview_curses::BM_USER, *iter); } lnav_data.ld_last_user_mark[tc] = -1; tc->reload_data(); } break; #endif case 's': if (lss) { vis_line_t next_top = vis_line_t(tc->get_top() + 2); if (!lss->is_time_offset_enabled()) { lnav_data.ld_rl_view->set_alt_value( HELP_MSG_1(T, "to disable elapsed-time mode")); } lss->set_time_offset(true); while (next_top < tc->get_inner_height()) { if (lss->find_line(lss->at(next_top))->is_continued()) { } else if (lss->get_line_accel_direction(next_top) == log_accel::A_DECEL) { --next_top; tc->set_top(next_top); break; } ++next_top; } } break; case 'S': if (lss) { vis_line_t next_top = tc->get_top(); if (!lss->is_time_offset_enabled()) { lnav_data.ld_rl_view->set_alt_value( HELP_MSG_1(T, "to disable elapsed-time mode")); } lss->set_time_offset(true); while (next_top < tc->get_inner_height()) { if (lss->find_line(lss->at(next_top))->is_continued()) { } else if (lss->get_line_accel_direction(next_top) == log_accel::A_DECEL) { --next_top; tc->set_top(next_top); break; } --next_top; } } break; case '1': case '2': case '3': case '4': case '5': case '6': if (lss) { int ten_minute = (ch - '0') * 10 * 60; time_t hour = rounddown(lnav_data.ld_top_time + (60 * 60) - ten_minute + 1, 60 * 60); vis_line_t line = lss->find_from_time(hour + ten_minute); tc->set_top(line); } break; case '!': back_ten(1); break; case '@': back_ten(2); break; case '#': back_ten(3); break; case '$': back_ten(4); break; case '%': back_ten(5); break; case '^': back_ten(6); break; case '9': if (lss) { double tenth = ((double)tc->get_inner_height()) / 10.0; tc->shift_top(vis_line_t(tenth)); } break; case '(': if (lss) { double tenth = ((double)tc->get_inner_height()) / 10.0; tc->shift_top(vis_line_t(-tenth)); } break; case '0': if (lss) { time_t first_time = lnav_data.ld_top_time; int step = 24 * 60 * 60; vis_line_t line = lss->find_from_time(roundup_size(first_time, step)); tc->set_top(line); } break; case ')': if (lss) { time_t day = rounddown(lnav_data.ld_top_time, 24 * 60 * 60); vis_line_t line = lss->find_from_time(day); --line; tc->set_top(line); } break; case 'D': case 'O': if (tc->get_top() == 0) { flash(); } else if (lss) { int step = ch == 'D' ? (24 * 60 * 60) : (60 * 60); time_t top_time = lnav_data.ld_top_time; vis_line_t line = lss->find_from_time(top_time - step); if (line != 0) { --line; } tc->set_top(line); lnav_data.ld_rl_view->set_alt_value(HELP_MSG_1(/, "to search")); } break; case 'd': case 'o': if (lss) { int step = ch == 'd' ? (24 * 60 * 60) : (60 * 60); vis_line_t line = lss->find_from_time(lnav_data.ld_top_time + step); tc->set_top(line); lnav_data.ld_rl_view->set_alt_value(HELP_MSG_1(/, "to search")); } break; case ':': if (lnav_data.ld_views[LNV_LOG].get_inner_height() > 0) { logfile_sub_source &lss = lnav_data.ld_log_source; textview_curses & log_view = lnav_data.ld_views[LNV_LOG]; content_line_t cl = lss.at(log_view.get_top()); logfile * lf = lss.find(cl); logfile::iterator ll = lf->begin() + cl; log_data_helper ldh(lss); lnav_data.ld_rl_view->clear_possibilities(LNM_COMMAND, "colname"); ldh.parse_line(log_view.get_top(), true); for (vector::iterator iter = ldh.ldh_namer->cn_names.begin(); iter != ldh.ldh_namer->cn_names.end(); ++iter) { lnav_data.ld_rl_view->add_possibility(LNM_COMMAND, "colname", *iter); } ldh.clear(); lnav_data.ld_rl_view->clear_possibilities(LNM_COMMAND, "line-time"); { struct timeval tv = lf->get_time_offset(); char buffer[64]; sql_strftime(buffer, sizeof(buffer), ll->get_time(), ll->get_millis(), 'T'); lnav_data.ld_rl_view->add_possibility(LNM_COMMAND, "line-time", buffer); sql_strftime(buffer, sizeof(buffer), ll->get_time() - tv.tv_sec, ll->get_millis() - (tv.tv_usec / 1000), 'T'); lnav_data.ld_rl_view->add_possibility(LNM_COMMAND, "line-time", buffer); } } lnav_data.ld_rl_view->add_possibility( LNM_COMMAND, "levelname", logline::level_names); lnav_data.ld_mode = LNM_COMMAND; lnav_data.ld_rl_view->focus(LNM_COMMAND, ":"); lnav_data.ld_bottom_source.set_prompt("Enter an lnav command: " "(Press " ANSI_BOLD("CTRL+]") " to abort)"); break; case '/': lnav_data.ld_mode = LNM_SEARCH; lnav_data.ld_previous_search = lnav_data.ld_last_search[tc - lnav_data.ld_views]; lnav_data.ld_search_start_line = tc->get_top(); add_view_text_possibilities(LNM_SEARCH, tc); lnav_data.ld_rl_view->focus(LNM_SEARCH, "/"); lnav_data.ld_bottom_source.set_prompt( "Enter a regular expression to search for: " "(Press " ANSI_BOLD("CTRL+]") " to abort)"); break; case ';': if (tc == &lnav_data.ld_views[LNV_LOG] || tc == &lnav_data.ld_views[LNV_DB] || tc == &lnav_data.ld_views[LNV_SCHEMA]) { textview_curses &log_view = lnav_data.ld_views[LNV_LOG]; lnav_data.ld_mode = LNM_SQL; setup_logline_table(); lnav_data.ld_rl_view->focus(LNM_SQL, ";"); lnav_data.ld_bottom_source.update_loading(0, 0); lnav_data.ld_status[LNS_BOTTOM].do_update(); field_overlay_source *fos; fos = (field_overlay_source *)log_view.get_overlay_source(); fos->fos_active_prev = fos->fos_active; if (!fos->fos_active) { fos->fos_active = true; tc->reload_data(); } lnav_data.ld_bottom_source.set_prompt("Enter an SQL query: (Press " ANSI_BOLD("CTRL+]") " to abort)"); } break; case 'p': field_overlay_source *fos; fos = (field_overlay_source *)lnav_data.ld_views[LNV_LOG]. get_overlay_source(); fos->fos_active = !fos->fos_active; tc->reload_data(); break; case 't': if (lnav_data.ld_text_source.current_file() == NULL) { flash(); lnav_data.ld_rl_view->set_value("No text files loaded"); } else if (toggle_view(&lnav_data.ld_views[LNV_TEXT])) { lnav_data.ld_rl_view->set_alt_value(HELP_MSG_2( f, F, "to switch to the next/previous file")); } break; case 'T': lnav_data.ld_log_source.toggle_time_offset(); if (lss->is_time_offset_enabled()) { lnav_data.ld_rl_view->set_alt_value( HELP_MSG_2(s, S, "to move forward/backward through slow downs")); } tc->reload_data(); break; case 'i': if (toggle_view(&lnav_data.ld_views[LNV_HISTOGRAM])) { lnav_data.ld_rl_view->set_alt_value( HELP_MSG_2(z, Z, "to zoom in/out")); } else { lnav_data.ld_rl_view->set_alt_value(""); } break; case 'I': { time_t log_top = lnav_data.ld_top_time; time_t hist_top = lnav_data.ld_hist_source.value_for_row(tc->get_top()); if (toggle_view(&lnav_data.ld_views[LNV_HISTOGRAM])) { hist_source &hs = lnav_data.ld_hist_source; tc = lnav_data.ld_view_stack.top(); tc->set_top(hs.row_for_value(log_top)); } else { tc = &lnav_data.ld_views[LNV_LOG]; lss = &lnav_data.ld_log_source; tc->set_top(lss->find_from_time(hist_top)); tc->set_needs_update(); } } break; case KEY_CTRL_G: toggle_view(&lnav_data.ld_views[LNV_GRAPH]); break; case '?': toggle_view(&lnav_data.ld_views[LNV_HELP]); break; case 'v': toggle_view(&lnav_data.ld_views[LNV_DB]); break; case 'V': { textview_curses *db_tc = &lnav_data.ld_views[LNV_DB]; db_label_source &dls = lnav_data.ld_db_rows; hist_source & hs = lnav_data.ld_db_source; if (toggle_view(db_tc)) { unsigned int lpc; for (lpc = 0; lpc < dls.dls_headers.size(); lpc++) { if (dls.dls_headers[lpc] != "log_line") { continue; } char linestr[64]; int line_number = (int)tc->get_top(); unsigned int row; snprintf(linestr, sizeof(linestr), "%d", line_number); for (row = 0; row < dls.dls_rows.size(); row++) { if (strcmp(dls.dls_rows[row][lpc], linestr) == 0) { vis_line_t db_line(hs.row_for_value(row)); db_tc->set_top(db_line); db_tc->set_needs_update(); break; } } break; } } else { int db_row = hs.value_for_row(db_tc->get_top()); unsigned int lpc; for (lpc = 0; lpc < dls.dls_headers.size(); lpc++) { if (dls.dls_headers[lpc] != "log_line") { continue; } unsigned int line_number; tc = &lnav_data.ld_views[LNV_LOG]; if (sscanf(dls.dls_rows[db_row][lpc], "%d", &line_number) && line_number < tc->listview_rows(*tc)) { tc->set_top(vis_line_t(line_number)); tc->set_needs_update(); } break; } } } break; case '\t': if (tc == &lnav_data.ld_views[LNV_DB]) { hist_source &hs = lnav_data.ld_db_source; db_label_source &dls = lnav_data.ld_db_rows; std::vector &displayed = hs.get_displayed_buckets(); std::vector::iterator start_iter, iter; start_iter = dls.dls_headers_to_graph.begin(); if (!displayed.empty()) { advance(start_iter, (int)displayed[0] + 1); } displayed.clear(); iter = find(start_iter, dls.dls_headers_to_graph.end(), true); if (iter != dls.dls_headers_to_graph.end()) { bucket_type_t type; type = bucket_type_t(distance(dls.dls_headers_to_graph.begin(), iter)); displayed.push_back(type); } if (displayed.empty()) { lnav_data.ld_rl_view->set_value("Graphing all values"); } else { int index = displayed[0]; lnav_data.ld_rl_view->set_value("Graphing column " ANSI_BOLD_START + dls.dls_headers[index] + ANSI_NORM); } tc->reload_data(); } break; // XXX I'm sure there must be a better way to handle the difference between // iterator and reverse_iterator. case KEY_BTAB: if (tc == &lnav_data.ld_views[LNV_DB]) { hist_source &hs = lnav_data.ld_db_source; db_label_source &dls = lnav_data.ld_db_rows; std::vector &displayed = hs.get_displayed_buckets(); std::vector::reverse_iterator start_iter, iter; start_iter = dls.dls_headers_to_graph.rbegin(); if (!displayed.empty()) { advance(start_iter, dls.dls_headers_to_graph.size() - (int)displayed[0]); } displayed.clear(); iter = find(start_iter, dls.dls_headers_to_graph.rend(), true); if (iter != dls.dls_headers_to_graph.rend()) { bucket_type_t type; type = bucket_type_t(distance(dls.dls_headers_to_graph.begin(), --iter.base())); displayed.push_back(type); } tc->reload_data(); } break; case 'X': lnav_data.ld_rl_view->set_value(execute_command("close")); break; case '\\': { vis_bookmarks &bm = tc->get_bookmarks(); string ex; for (bookmark_vector::iterator iter = bm[&BM_EXAMPLE].begin(); iter != bm[&BM_EXAMPLE].end(); ++iter) { string line; tc->get_sub_source()->text_value_for_line(*tc, *iter, line); ex += line + "\n"; } lnav_data.ld_views[LNV_EXAMPLE].set_sub_source(new plain_text_source( ex)); ensure_view(&lnav_data.ld_views[LNV_EXAMPLE]); } break; case 'r': lnav_data.ld_session_file_index = (lnav_data.ld_session_file_index + 1) % lnav_data.ld_session_file_names.size(); reset_session(); load_session(); rebuild_indexes(true); break; case 'R': if (lnav_data.ld_session_file_index == 0) { lnav_data.ld_session_file_index = lnav_data.ld_session_file_names.size() - 1; } else{ lnav_data.ld_session_file_index -= 1; } reset_session(); load_session(); rebuild_indexes(true); break; case KEY_CTRL_R: reset_session(); rebuild_indexes(true); lnav_data.ld_rl_view->set_alt_value(HELP_MSG_2( r, R, "to restore the next/previous session")); break; case KEY_CTRL_W: execute_command(lnav_data.ld_views[LNV_LOG].get_word_wrap() ? "disable-word-wrap" : "enable-word-wrap"); break; default: log_warning("unhandled %d", ch); lnav_data.ld_rl_view->set_value("Unrecognized keystroke, press " ANSI_BOLD("?") " to view help"); flash(); break; } } static void handle_rl_key(int ch) { switch (ch) { case KEY_PPAGE: case KEY_NPAGE: handle_paging_key(ch); break; case KEY_CTRL_RBRACKET: lnav_data.ld_rl_view->abort(); break; default: lnav_data.ld_rl_view->handle_key(ch); break; } } readline_context::command_map_t lnav_commands; string execute_command(string cmdline) { stringstream ss(cmdline); vector args; string buf, msg; log_info("Executing: %s", cmdline.c_str()); while (ss >> buf) { args.push_back(buf); } if (args.size() > 0) { readline_context::command_map_t::iterator iter; if ((iter = lnav_commands.find(args[0])) == lnav_commands.end()) { msg = "error: unknown command - " + args[0]; } else { msg = iter->second(cmdline, args); } } return msg; } string execute_sql(string sql, string &alt_msg) { db_label_source & dls = lnav_data.ld_db_rows; hist_source & hs = lnav_data.ld_db_source; auto_mem stmt(sqlite3_finalize); string stmt_str = trim(sql); string retval; int retcode; log_info("Executing SQL: %s", sql.c_str()); lnav_data.ld_bottom_source.grep_error(""); if (stmt_str == ".schema") { alt_msg = ""; ensure_view(&lnav_data.ld_views[LNV_SCHEMA]); lnav_data.ld_mode = LNM_PAGING; return ""; } hs.clear(); hs.get_displayed_buckets().clear(); dls.clear(); dls.dls_stmt_str = stmt_str; retcode = sqlite3_prepare_v2(lnav_data.ld_db.in(), stmt_str.c_str(), -1, stmt.out(), NULL); if (retcode != SQLITE_OK) { const char *errmsg = sqlite3_errmsg(lnav_data.ld_db); retval = "error: " + string(errmsg); alt_msg = ""; } else if (stmt == NULL) { retval = ""; alt_msg = ""; } else { bool done = false; int param_count; param_count = sqlite3_bind_parameter_count(stmt.in()); for (int lpc = 0; lpc < param_count; lpc++) { const char *name; name = sqlite3_bind_parameter_name(stmt.in(), lpc + 1); if (name[0] == '$') { const char *env_value; if ((env_value = getenv(&name[1])) != NULL) { sqlite3_bind_text(stmt.in(), lpc + 1, env_value, -1, SQLITE_STATIC); } } } if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->set_value("Executing query: " + sql + " ..."); lnav_data.ld_rl_view->do_update(); } lnav_data.ld_log_source.text_clear_marks(&BM_QUERY); while (!done) { retcode = sqlite3_step(stmt.in()); switch (retcode) { case SQLITE_OK: case SQLITE_DONE: done = true; break; case SQLITE_ROW: sql_callback(stmt.in()); break; default: { const char *errmsg; log_error("sqlite3_step error code: %d", retcode); errmsg = sqlite3_errmsg(lnav_data.ld_db); retval = "error: " + string(errmsg); done = true; } break; } } } if (retcode == SQLITE_DONE) { lnav_data.ld_views[LNV_LOG].reload_data(); lnav_data.ld_views[LNV_DB].reload_data(); lnav_data.ld_views[LNV_DB].set_left(0); if (dls.dls_rows.size() > 0) { vis_bookmarks &bm = lnav_data.ld_views[LNV_LOG].get_bookmarks(); if (dls.dls_headers.size() == 1 && !bm[&BM_QUERY].empty()) { retval = ""; alt_msg = HELP_MSG_2( y, Y, "to move forward/backward through query results " "in the log view"); } else if (dls.dls_rows.size() == 1) { string row; hs.text_value_for_line(lnav_data.ld_views[LNV_DB], 1, row, true); retval = "SQL Result: " + row; } else { char row_count[32]; ensure_view(&lnav_data.ld_views[LNV_DB]); snprintf(row_count, sizeof(row_count), ANSI_BOLD("%'d") " row(s) matched", (int)dls.dls_rows.size()); retval = row_count; alt_msg = HELP_MSG_2( y, Y, "to move forward/backward through query results " "in the log view"); } } #ifdef HAVE_SQLITE3_STMT_READONLY else if (sqlite3_stmt_readonly(stmt.in())) { retval = "No rows matched"; alt_msg = ""; } #endif } if (!(lnav_data.ld_flags & LNF_HEADLESS)) { lnav_data.ld_bottom_source.update_loading(0, 0); lnav_data.ld_status[LNS_BOTTOM].do_update(); { field_overlay_source *fos; fos = (field_overlay_source *)lnav_data.ld_views[LNV_LOG]. get_overlay_source(); fos->fos_active = fos->fos_active_prev; redo_search(LNV_DB); } } lnav_data.ld_views[LNV_LOG].reload_data(); return retval; } static void execute_file(string path) { FILE *file; if (path == "-") { file = stdin; } else if ((file = fopen(path.c_str(), "r")) == NULL) { return; } int line_number = 0; char *line = NULL; size_t line_max_size; ssize_t line_size; while ((line_size = getline(&line, &line_max_size, file)) != -1) { line_number += 1; if (trim(line).empty()) { continue; } if (line[0] == '#') { continue; } string rc, alt_msg; if (line[line_size - 1] == '\n') { line[line_size - 1] = '\0'; } switch (line[0]) { case ':': rc = execute_command(&line[1]); break; case '/': case ';': setup_logline_table(); rc = execute_sql(&line[1], alt_msg); break; case '|': execute_file(&line[1]); break; default: rc = execute_command(line); break; } if (rescan_files()) { rebuild_indexes(true); } log_info("%s:%d:execute result -- %s", path.c_str(), line_number, rc.c_str()); } if (file != stdin) { fclose(file); } } void execute_init_commands(vector > &msgs) { if (lnav_data.ld_commands.empty()) { return; } for (std::list::iterator iter = lnav_data.ld_commands.begin(); iter != lnav_data.ld_commands.end(); ++iter) { string msg, alt_msg; switch (iter->at(0)) { case ':': msg = execute_command(iter->substr(1)); break; case '/': case ';': setup_logline_table(); msg = execute_sql(iter->substr(1), alt_msg); break; case '|': execute_file(iter->substr(1)); break; } msgs.push_back(make_pair(msg, alt_msg)); if (rescan_files()) { rebuild_indexes(true); } } lnav_data.ld_commands.clear(); } int sql_callback(sqlite3_stmt *stmt) { logfile_sub_source &lss = lnav_data.ld_log_source; db_label_source & dls = lnav_data.ld_db_rows; hist_source & hs = lnav_data.ld_db_source; int ncols = sqlite3_column_count(stmt); int row_number; int lpc, retval = 0; row_number = dls.dls_rows.size(); dls.dls_rows.resize(row_number + 1); if (dls.dls_headers.empty()) { for (lpc = 0; lpc < ncols; lpc++) { int type = sqlite3_column_type(stmt, lpc); string colname = sqlite3_column_name(stmt, lpc); bool graphable; graphable = ((type == SQLITE_INTEGER || type == SQLITE_FLOAT) && !binary_search(lnav_data.ld_db_key_names.begin(), lnav_data.ld_db_key_names.end(), colname)); dls.push_header(colname, type, graphable); if (graphable) { hs.set_role_for_type(bucket_type_t(lpc), view_colors::singleton(). next_plain_highlight()); } } } for (lpc = 0; lpc < ncols; lpc++) { const char *value = (const char *)sqlite3_column_text(stmt, lpc); double num_value = 0.0; dls.push_column(value); if (dls.dls_headers[lpc] == "log_line") { int line_number = -1; if (sscanf(value, "%d", &line_number) == 1) { lss.text_mark(&BM_QUERY, line_number, true); } } if (dls.dls_headers_to_graph[lpc]) { sscanf(value, "%lf", &num_value); hs.add_value(row_number, bucket_type_t(lpc), num_value); } else { hs.add_empty_value(row_number); } } return retval; } void execute_search(lnav_view_t view, const std::string ®ex_orig) { auto_ptr &gc = lnav_data.ld_search_child[view]; textview_curses & tc = lnav_data.ld_views[view]; std::string regex = regex_orig; if ((gc.get() == NULL) || (regex != lnav_data.ld_last_search[view])) { const char *errptr; pcre * code = NULL; int eoff; bool quoted = false; tc.match_reset(); if (regex.empty() && gc.get() != NULL) { tc.grep_begin(*(gc->get_grep_proc())); tc.grep_end(*(gc->get_grep_proc())); } gc.reset(); log_debug("start search for: '%s'", regex.c_str()); if (regex.empty()) { lnav_data.ld_bottom_source.grep_error(""); } else if ((code = pcre_compile(regex.c_str(), PCRE_CASELESS, &errptr, &eoff, NULL)) == NULL) { lnav_data.ld_bottom_source.grep_error( "regexp error: " + string(errptr)); quoted = true; regex = pcrecpp::RE::QuoteMeta(regex); log_info("invalid search regex, using quoted: %s", regex.c_str()); if ((code = pcre_compile(regex.c_str(), PCRE_CASELESS, &errptr, &eoff, NULL)) == NULL) { log_error("Unable to compile quoted regex: %s", regex.c_str()); } } if (code != NULL) { textview_curses::highlighter hl( code, false, view_colors::VCR_SEARCH); if (!quoted) { lnav_data.ld_bottom_source.grep_error(""); } lnav_data.ld_bottom_source.set_prompt(""); textview_curses::highlight_map_t &hm = tc.get_highlights(); hm["$search"] = hl; auto_ptr gp(new grep_proc(code, tc, lnav_data.ld_max_fd, lnav_data.ld_read_fds)); gp->queue_request(grep_line_t(tc.get_top())); if (tc.get_top() > 0) { gp->queue_request(grep_line_t(0), grep_line_t(tc.get_top())); } gp->start(); gp->set_sink(&tc); tc.set_follow_search(true); auto_ptr gh( new grep_highlighter(gp, "$search", hm)); gc = gh; } } lnav_data.ld_last_search[view] = regex; } static void rl_search_internal(void *dummy, readline_curses *rc, bool complete = false) { string term_val; string name; switch (lnav_data.ld_mode) { case LNM_SEARCH: name = "$search"; break; case LNM_CAPTURE: require(0); name = "$capture"; break; case LNM_COMMAND: return; case LNM_SQL: term_val = trim(rc->get_value() + ";"); if (term_val.size() > 0 && term_val[0] == '.') { lnav_data.ld_bottom_source.grep_error(""); } else if (!sqlite3_complete(term_val.c_str())) { lnav_data.ld_bottom_source. grep_error("sql error: incomplete statement"); } else { auto_mem stmt(sqlite3_finalize); int retcode; retcode = sqlite3_prepare_v2(lnav_data.ld_db, rc->get_value().c_str(), -1, stmt.out(), NULL); if (retcode != SQLITE_OK) { const char *errmsg = sqlite3_errmsg(lnav_data.ld_db); lnav_data.ld_bottom_source. grep_error(string("sql error: ") + string(errmsg)); } else { lnav_data.ld_bottom_source.grep_error(""); } } return; default: require(0); break; } textview_curses *tc = lnav_data.ld_view_stack.top(); lnav_view_t index = (lnav_view_t)(tc - lnav_data.ld_views); if (!complete) tc->set_top(lnav_data.ld_search_start_line); execute_search(index, rc->get_value()); } static void rl_search(void *dummy, readline_curses *rc) { rl_search_internal(dummy, rc); } static void rl_abort(void *dummy, readline_curses *rc) { textview_curses *tc = lnav_data.ld_view_stack.top(); lnav_view_t index = (lnav_view_t)(tc - lnav_data.ld_views); lnav_data.ld_bottom_source.set_prompt(""); lnav_data.ld_bottom_source.grep_error(""); switch (lnav_data.ld_mode) { case LNM_SEARCH: tc->set_top(lnav_data.ld_search_start_line); execute_search(index, lnav_data.ld_previous_search); break; case LNM_SQL: { field_overlay_source *fos; fos = (field_overlay_source *)lnav_data.ld_views[LNV_LOG]. get_overlay_source(); fos->fos_active = fos->fos_active_prev; tc->reload_data(); break; } default: break; } lnav_data.ld_mode = LNM_PAGING; } static void rl_callback(void *dummy, readline_curses *rc) { lnav_data.ld_bottom_source.set_prompt(""); string alt_msg; switch (lnav_data.ld_mode) { case LNM_PAGING: require(0); break; case LNM_COMMAND: lnav_data.ld_mode = LNM_PAGING; rc->set_alt_value(""); rc->set_value(execute_command(rc->get_value())); break; case LNM_SEARCH: case LNM_CAPTURE: rl_search_internal(dummy, rc, true); if (rc->get_value().size() > 0) { lnav_data.ld_view_stack.top()->set_follow_search(false); lnav_data.ld_rl_view-> add_possibility(LNM_COMMAND, "filter", rc->get_value()); rc->set_value("search: " + rc->get_value()); rc->set_alt_value(HELP_MSG_2( n, N, "to move forward/backward through search results")); } lnav_data.ld_mode = LNM_PAGING; break; case LNM_SQL: rc->set_value(execute_sql(rc->get_value(), alt_msg)); rc->set_alt_value(alt_msg); lnav_data.ld_mode = LNM_PAGING; break; } } static void rl_display_matches(void *dummy, readline_curses *rc) { const std::vector &matches = rc->get_matches(); textview_curses &tc = lnav_data.ld_match_view; unsigned long width, height; int max_len, cols, rows, match_height, bottom_height; getmaxyx(lnav_data.ld_window, height, width); max_len = rc->get_max_match_length() + 2; cols = max(1UL, width / max_len); rows = (matches.size() + cols - 1) / cols; match_height = min((unsigned long)rows, (height - 4) / 2); bottom_height = match_height + 1 + rc->get_height(); for (int lpc = 0; lpc < LNV__MAX; lpc++) { lnav_data.ld_views[lpc].set_height(vis_line_t(-bottom_height)); } lnav_data.ld_status[LNS_BOTTOM].set_top(-bottom_height); if (tc.get_sub_source() != NULL) { delete tc.get_sub_source(); } if (cols == 1) { tc.set_sub_source(new plain_text_source(rc->get_matches())); } else { std::vector horiz_matches; horiz_matches.resize(rows); for (int lpc = 0; lpc < matches.size(); lpc++) { int curr_row = lpc % rows; horiz_matches[curr_row].append(matches[lpc]); horiz_matches[curr_row].append( max_len - matches[lpc].length(), ' '); } tc.set_sub_source(new plain_text_source(horiz_matches)); } if (match_height > 0) { tc.set_window(lnav_data.ld_window); tc.set_y(height - bottom_height + 1); tc.set_height(vis_line_t(match_height)); tc.reload_data(); } else { tc.set_window(NULL); } } static void rl_display_next(void *dummy, readline_curses *rc) { textview_curses &tc = lnav_data.ld_match_view; if (tc.get_top() >= (tc.get_top_for_last_row() - 1)) { tc.set_top(vis_line_t(0)); } else { tc.shift_top(tc.get_height()); } } static void usage(void) { const char *usage_msg = "usage: %s [-hVsar] [logfile1 logfile2 ...]\n" "\n" "A curses-based log file viewer that indexes log messages by type\n" "and time to make it easier to navigate through files quickly.\n" "\n" "Key bindings:\n" " ? View/leave the online help text.\n" " q Quit the program.\n" "\n" "Options:\n" " -h Print this message, then exit.\n" " -H Display the internal help text.\n" " -I path An additional configuration directory.\n" " -C Check configuration and then exit.\n" " -d file Write debug messages to the given file.\n" " -V Print version information.\n" "\n" " -s Load the most recent syslog messages file.\n" " -a Load all of the most recent log file types.\n" " -r Load older rotated log files as well.\n" " -t Prepend timestamps to the lines of data being read in\n" " on the standard input.\n" " -w file Write the contents of the standard input to this file.\n" "\n" " -c cmd Execute a command after the files have been loaded.\n" " -f path Execute the commands in the given file.\n" " -n Run without the curses UI. (headless mode)\n" " -q Do not print the log messages after executing all\n" " of the commands.\n" "\n" "Optional arguments:\n" " logfile1 The log files or directories to view. If a\n" " directory is given, all of the files in the\n" " directory will be loaded.\n" "\n" "Examples:\n" " To load and follow the syslog file:\n" " $ lnav -s\n" "\n" " To load all of the files in /var/log:\n" " $ lnav /var/log\n" "\n" " To watch the output of make with timestamps prepended:\n" " $ make 2>&1 | lnav -t\n" "\n" "Version: " PACKAGE_STRING "\n"; fprintf(stderr, usage_msg, lnav_data.ld_program_name); } static pcre *xpcre_compile(const char *pattern, int options = 0) { const char *errptr; pcre * retval; int eoff; if ((retval = pcre_compile(pattern, options, &errptr, &eoff, NULL)) == NULL) { fprintf(stderr, "internal error: failed to compile -- %s\n", pattern); fprintf(stderr, "internal error: %s\n", errptr); exit(1); } return retval; } /** * Callback used to keep track of the timestamps for the top and bottom lines * in the log view. This function is intended to be used as the callback * function in a view_action. * * @param lv The listview object that contains the log */ static void update_times(void *, listview_curses *lv) { if (lv == &lnav_data.ld_views[LNV_LOG] && lv->get_inner_height() > 0) { logfile_sub_source &lss = lnav_data.ld_log_source; logline *ll; ll = lss.find_line(lss.at(lv->get_top())); lnav_data.ld_top_time = ll->get_time(); lnav_data.ld_top_time_millis = ll->get_millis(); ll = lss.find_line(lss.at(lv->get_bottom())); lnav_data.ld_bottom_time = ll->get_time(); lnav_data.ld_bottom_time_millis = ll->get_millis(); } if (lv == &lnav_data.ld_views[LNV_HISTOGRAM] && lv->get_inner_height() > 0) { hist_source &hs = lnav_data.ld_hist_source; lnav_data.ld_top_time = hs.value_for_row(lv->get_top()); lnav_data.ld_top_time_millis = 0; lnav_data.ld_bottom_time = hs.value_for_row(lv->get_bottom()); lnav_data.ld_bottom_time_millis = 0; } } /** * Functor used to compare files based on their device and inode number. */ struct same_file { same_file(const struct stat &stat) : sf_stat(stat) { }; /** * Compare the given log file against the 'stat' given in the constructor. * @param lf The log file to compare. * @return True if the dev/inode values in the stat given in the * constructor matches the stat in the logfile object. */ bool operator()(const logfile *lf) const { return this->sf_stat.st_dev == lf->get_stat().st_dev && this->sf_stat.st_ino == lf->get_stat().st_ino; }; const struct stat &sf_stat; }; /** * Try to load the given file as a log file. If the file has not already been * loaded, it will be loaded. If the file has already been loaded, the file * name will be updated. * * @param filename The file name to check. * @param fd An already-opened descriptor for 'filename'. * @param required Specifies whether or not the file must exist and be valid. */ static void watch_logfile(string filename, int fd, bool required) { list::iterator file_iter; struct stat st; int rc; if (fd != -1) { rc = fstat(fd, &st); } else { rc = stat(filename.c_str(), &st); } if (rc == 0) { if (!S_ISREG(st.st_mode)) { if (required) { rc = -1; errno = EINVAL; } else { return; } } } if (rc == -1) { if (required) { throw logfile::error(filename, errno); } else{ return; } } file_iter = find_if(lnav_data.ld_files.begin(), lnav_data.ld_files.end(), same_file(st)); if (file_iter == lnav_data.ld_files.end()) { if (find(lnav_data.ld_other_files.begin(), lnav_data.ld_other_files.end(), filename) == lnav_data.ld_other_files.end()) { file_format_t ff = detect_file_format(filename); switch (ff) { case FF_SQLITE_DB: lnav_data.ld_other_files.push_back(filename); attach_sqlite_db(lnav_data.ld_db.in(), filename); break; default: /* It's a new file, load it in. */ logfile *lf = new logfile(filename, fd); lnav_data.ld_files.push_back(lf); lnav_data.ld_text_source.tss_files.push_back(lf); break; } } } else { /* The file is already loaded, but has been found under a different * name. We just need to update the stored file name. */ (*file_iter)->set_filename(filename); } } /** * Expand a glob pattern and call watch_logfile with the file names that match * the pattern. * @param path The glob pattern to expand. * @param required Passed to watch_logfile. */ static void expand_filename(string path, bool required) { static_root_mem gl; if (glob(path.c_str(), GLOB_NOCHECK, NULL, gl.inout()) == 0) { int lpc; if (gl->gl_pathc == 1 /*&& gl.gl_matchc == 0*/) { /* It's a pattern that doesn't match any files * yet, allow it through since we'll load it in * dynamically. */ required = false; } if (gl->gl_pathc > 1 || strcmp(path.c_str(), gl->gl_pathv[0]) != 0) { required = false; } for (lpc = 0; lpc < (int)gl->gl_pathc; lpc++) { auto_mem abspath; if ((abspath = realpath(gl->gl_pathv[lpc], NULL)) == NULL) { if (required) { fprintf(stderr, "Cannot find file: %s -- %s", gl->gl_pathv[lpc], strerror(errno)); } } else { watch_logfile(abspath.in(), -1, required); } } } } static bool rescan_files(bool required) { set >::iterator iter; list::iterator file_iter; bool retval = false; for (iter = lnav_data.ld_file_names.begin(); iter != lnav_data.ld_file_names.end(); iter++) { if (iter->second == -1) { expand_filename(iter->first, required); if (lnav_data.ld_flags & LNF_ROTATED) { string path = iter->first + ".*"; expand_filename(path, false); } } else { watch_logfile(iter->first, iter->second, required); } } for (file_iter = lnav_data.ld_files.begin(); file_iter != lnav_data.ld_files.end(); ) { logfile *lf = *file_iter; if (!lf->exists() || lf->is_closed()) { std::list::iterator tss_iter; log_info("file has been deleted/closed -- %s", lf->get_filename().c_str()); lnav_data.ld_file_names.erase(make_pair(lf->get_filename(), lf->get_fd())); lnav_data.ld_text_source.tss_files.remove(lf); lnav_data.ld_log_source.remove_file(lf); file_iter = lnav_data.ld_files.erase(file_iter); delete lf; retval = true; } else { ++file_iter; } } return retval; } static string execute_action(log_data_helper &ldh, int value_index, const string &action_name) { std::map::const_iterator iter; logline_value &lv = ldh.ldh_line_values[value_index]; logfile *lf = ldh.ldh_file; const log_format *format = lf->get_format(); pid_t child_pid; string retval; iter = format->lf_action_defs.find(action_name); const log_format::action_def &action = iter->second; auto_pipe in_pipe(STDIN_FILENO); auto_pipe out_pipe(STDOUT_FILENO); auto_pipe err_pipe(STDERR_FILENO); in_pipe.open(); if (action.ad_capture_output) out_pipe.open(); err_pipe.open(); child_pid = fork(); in_pipe.after_fork(child_pid); out_pipe.after_fork(child_pid); err_pipe.after_fork(child_pid); switch (child_pid) { case -1: retval = "error: unable to fork child process -- " + string(strerror(errno)); break; case 0: { const char *args[action.ad_cmdline.size() + 1]; set path_set(format->get_source_path()); char env_buffer[64]; int value_line; string path; setenv("LNAV_ACTION_FILE", lf->get_filename().c_str(), 1); snprintf(env_buffer, sizeof(env_buffer), "%ld", (ldh.ldh_line - lf->begin()) + 1); setenv("LNAV_ACTION_FILE_LINE", env_buffer, 1); snprintf(env_buffer, sizeof(env_buffer), "%d", ldh.ldh_y_offset + 1); setenv("LNAV_ACTION_MSG_LINE", env_buffer, 1); setenv("LNAV_ACTION_VALUE_NAME", lv.lv_name.c_str(), 1); value_line = ldh.ldh_y_offset - ldh.get_value_line(lv) + 1; snprintf(env_buffer, sizeof(env_buffer), "%d", value_line); setenv("LNAV_ACTION_VALUE_LINE", env_buffer, 1); for (set::iterator path_iter = path_set.begin(); path_iter != path_set.end(); ++path_iter) { if (!path.empty()) { path += ":"; } path += *path_iter; } path += ":" + string(getenv("PATH")); setenv("PATH", path.c_str(), 1); for (size_t lpc = 0; lpc < action.ad_cmdline.size(); lpc++) { args[lpc] = action.ad_cmdline[lpc].c_str(); } args[action.ad_cmdline.size()] = NULL; execvp(args[0], (char *const *) args); fprintf(stderr, "error: could not exec process -- %s:%s\n", args[0], strerror(errno)); _exit(0); } break; default: { static int exec_count = 0; string value = lv.to_string(); line_buffer lb; off_t off = 0; line_value lv; lnav_data.ld_children.push_back(child_pid); if (write(in_pipe.write_end(), value.c_str(), value.size()) == -1) { perror("execute_action write"); } in_pipe.close(); lb.set_fd(err_pipe.read_end()); lb.read_line(off, lv); if (out_pipe.read_end() != -1) { piper_proc *pp = new piper_proc(out_pipe.read_end(), false); char desc[128]; lnav_data.ld_pipers.push_back(pp); snprintf(desc, sizeof(desc), "[%d] Output of %s", exec_count++, action.ad_cmdline[0].c_str()); lnav_data.ld_file_names.insert(make_pair( desc, pp->get_fd())); lnav_data.ld_files_to_front.push_back(make_pair(desc, 0)); } retval = string(lv.lv_start, lv.lv_len); } break; } return retval; } class action_delegate : public text_delegate { public: action_delegate(logfile_sub_source &lss) : ad_log_helper(lss), ad_press_line(-1) { }; virtual bool text_handle_mouse(textview_curses &tc, mouse_event &me) { bool retval = false; if (me.me_button != BUTTON_LEFT) { return false; } vis_line_t mouse_line = vis_line_t(tc.get_top() + me.me_y); int mouse_left = tc.get_left() + me.me_x; switch (me.me_state) { case BUTTON_STATE_PRESSED: if (mouse_line >= vis_line_t(0) && mouse_line <= tc.get_bottom()) { size_t line_end_index = 0; int x_offset; this->ad_press_line = mouse_line; this->ad_log_helper.parse_line(mouse_line, true); this->ad_log_helper.get_line_bounds(this->ad_line_index, line_end_index); struct line_range lr(this->ad_line_index, line_end_index); this->ad_press_value = -1; x_offset = this->ad_line_index + mouse_left; if (lr.contains(x_offset)) { for (size_t lpc = 0; lpc < this->ad_log_helper.ldh_line_values.size(); lpc++) { logline_value &lv = this->ad_log_helper.ldh_line_values[lpc]; if (lv.lv_origin.contains(x_offset)) { this->ad_press_value = lpc; break; } } } } break; case BUTTON_STATE_DRAGGED: if (mouse_line != this->ad_press_line) { this->ad_press_value = -1; } if (this->ad_press_value != -1) { retval = true; } break; case BUTTON_STATE_RELEASED: if (this->ad_press_value != -1 && this->ad_press_line == mouse_line) { logline_value &lv = this->ad_log_helper.ldh_line_values[this->ad_press_value]; int x_offset = this->ad_line_index + mouse_left; if (lv.lv_origin.contains(x_offset)) { logfile *lf = this->ad_log_helper.ldh_file; const vector *actions; actions = lf->get_format()->get_actions(lv); if (actions != NULL && !actions->empty()) { string rc = execute_action( this->ad_log_helper, this->ad_press_value, actions->at(0)); lnav_data.ld_rl_view->set_value(rc); } } retval = true; } break; } return retval; }; log_data_helper ad_log_helper; vis_line_t ad_press_line; int ad_press_value; size_t ad_line_index; }; class lnav_behavior : public mouse_behavior { public: enum lb_mode_t { LB_MODE_NONE, LB_MODE_DOWN, LB_MODE_UP, LB_MODE_DRAG }; lnav_behavior() {}; int scroll_polarity(int button) { return button == xterm_mouse::XT_SCROLL_UP ? -1 : 1; }; void mouse_event(int button, bool release, int x, int y) { textview_curses * tc = lnav_data.ld_view_stack.top(); struct mouse_event me; switch (button & xterm_mouse::XT_BUTTON__MASK) { case xterm_mouse::XT_BUTTON1: me.me_button = BUTTON_LEFT; break; case xterm_mouse::XT_BUTTON2: me.me_button = BUTTON_MIDDLE; break; case xterm_mouse::XT_BUTTON3: me.me_button = BUTTON_RIGHT; break; case xterm_mouse::XT_SCROLL_UP: me.me_button = BUTTON_SCROLL_UP; break; case xterm_mouse::XT_SCROLL_DOWN: me.me_button = BUTTON_SCROLL_DOWN; break; } if (button & xterm_mouse::XT_DRAG_FLAG) { me.me_state = BUTTON_STATE_DRAGGED; } else if (release) { me.me_state = BUTTON_STATE_RELEASED; } else { me.me_state = BUTTON_STATE_PRESSED; } gettimeofday(&me.me_time, NULL); me.me_x = x - 1; me.me_y = y - tc->get_y() - 1; tc->handle_mouse(me); }; private: }; static void handle_key(int ch) { switch (ch) { case CEOF: case KEY_RESIZE: break; default: switch (lnav_data.ld_mode) { case LNM_PAGING: handle_paging_key(ch); break; case LNM_COMMAND: case LNM_SEARCH: case LNM_CAPTURE: case LNM_SQL: handle_rl_key(ch); break; default: require(0); break; } } } void update_hits(void *dummy, textview_curses *tc) { if (!lnav_data.ld_view_stack.empty() && tc == lnav_data.ld_view_stack.top()) { lnav_data.ld_bottom_source.update_hits(tc); } } static void looper(void) { try { readline_context command_context("cmd", &lnav_commands); readline_context search_context("search"); readline_context index_context("capture"); readline_context sql_context("sql", NULL, false); readline_curses rlc; int lpc; search_context .set_append_character(0) .set_highlighter(readline_regex_highlighter); sql_context.set_highlighter(readline_sqlite_highlighter); listview_curses::action::broadcaster &sb = lnav_data.ld_scroll_broadcaster; rlc.add_context(LNM_COMMAND, command_context); rlc.add_context(LNM_SEARCH, search_context); rlc.add_context(LNM_CAPTURE, index_context); rlc.add_context(LNM_SQL, sql_context); rlc.start(); lnav_data.ld_rl_view = &rlc; lnav_data.ld_rl_view->add_possibility( LNM_COMMAND, "graph", "\\d+(?:\\.\\d+)?"); lnav_data.ld_rl_view->add_possibility( LNM_COMMAND, "graph", "([:= \\t]\\d+(?:\\.\\d+)?)"); lnav_data.ld_rl_view->add_possibility( LNM_COMMAND, "viewname", lnav_view_strings); (void)signal(SIGINT, sigint); (void)signal(SIGTERM, sigint); (void)signal(SIGWINCH, sigwinch); (void)signal(SIGCHLD, sigchld); screen_curses sc; lnav_behavior lb; ui_periodic_timer::singleton(); lnav_data.ld_mouse.set_behavior(&lb); lnav_data.ld_mouse.set_enabled(check_experimental("mouse")); lnav_data.ld_window = sc.get_window(); keypad(stdscr, TRUE); (void)nonl(); (void)cbreak(); (void)noecho(); (void)nodelay(lnav_data.ld_window, 1); define_key("\033Od", KEY_BEG); define_key("\033Oc", KEY_END); view_colors::singleton().init(); rlc.set_window(lnav_data.ld_window); rlc.set_y(-1); rlc.set_perform_action(readline_curses::action(rl_callback)); rlc.set_timeout_action(readline_curses::action(rl_search)); rlc.set_abort_action(readline_curses::action(rl_abort)); rlc.set_display_match_action( readline_curses::action(rl_display_matches)); rlc.set_display_next_action( readline_curses::action(rl_display_next)); rlc.set_alt_value(HELP_MSG_2( e, E, "to move forward/backward through error messages")); (void)curs_set(0); lnav_data.ld_view_stack.push(&lnav_data.ld_views[LNV_LOG]); update_view_name(); for (lpc = 0; lpc < LNV__MAX; lpc++) { lnav_data.ld_views[lpc].set_window(lnav_data.ld_window); lnav_data.ld_views[lpc].set_y(1); lnav_data.ld_views[lpc]. set_height(vis_line_t(-(rlc.get_height() + 1))); lnav_data.ld_views[lpc]. set_scroll_action(sb.get_functor()); lnav_data.ld_views[lpc].set_search_action( textview_curses::action(update_hits)); } lnav_data.ld_status[LNS_TOP].set_top(0); lnav_data.ld_status[LNS_BOTTOM].set_top(-(rlc.get_height() + 1)); for (lpc = 0; lpc < LNS__MAX; lpc++) { lnav_data.ld_status[lpc].set_window(lnav_data.ld_window); } lnav_data.ld_status[LNS_TOP].set_data_source( &lnav_data.ld_top_source); lnav_data.ld_status[LNS_BOTTOM].set_data_source( &lnav_data.ld_bottom_source); lnav_data.ld_match_view.set_show_bottom_border(true); sb.push_back(view_action(update_times)); sb.push_back(&lnav_data.ld_top_source.filename_wire); sb.push_back(&lnav_data.ld_bottom_source.line_number_wire); sb.push_back(&lnav_data.ld_bottom_source.percent_wire); sb.push_back(&lnav_data.ld_bottom_source.marks_wire); sb.push_back(&lnav_data.ld_term_extra.filename_wire); FD_ZERO(&lnav_data.ld_read_fds); FD_SET(STDIN_FILENO, &lnav_data.ld_read_fds); lnav_data.ld_max_fd = max(STDIN_FILENO, rlc.update_fd_set(lnav_data.ld_read_fds)); lnav_data.ld_status[0].window_change(); lnav_data.ld_status[1].window_change(); execute_file(dotlnav_path("session")); lnav_data.ld_scroll_broadcaster.invoke(lnav_data.ld_view_stack.top()); bool session_loaded = false; struct timeval curr_to = { 0, 330000 }; while (lnav_data.ld_looping) { fd_set ready_rfds = lnav_data.ld_read_fds; struct timeval to = curr_to; int rc; lnav_data.ld_top_source.update_time(); if (rescan_files()) { rebuild_indexes(true); } lnav_data.ld_status[LNS_TOP].do_update(); lnav_data.ld_view_stack.top()->do_update(); lnav_data.ld_match_view.do_update(); lnav_data.ld_status[LNS_BOTTOM].do_update(); rlc.do_update(); refresh(); rc = select(lnav_data.ld_max_fd + 1, &ready_rfds, NULL, NULL, &to); if (rc == -1 && errno == EINTR) { rc = 0; } if (rc < 0) { switch (errno) { case EBADF: { int lpc, fd_flags; log_error("bad file descriptor"); for (lpc = 0; lpc < FD_SETSIZE; lpc++) { if (fcntl(lpc, F_GETFD, &fd_flags) == -1 && FD_ISSET(lpc, &lnav_data.ld_read_fds)) { log_error("bad fd %d", lpc); } } lnav_data.ld_looping = false; } break; default: log_error("select %s", strerror(errno)); lnav_data.ld_looping = false; break; } } else if (rc == 0) { static bool initial_build = false; rebuild_indexes(false); if (!initial_build && lnav_data.ld_log_source.text_line_count() == 0 && lnav_data.ld_text_source.text_line_count() > 0) { toggle_view(&lnav_data.ld_views[LNV_TEXT]); lnav_data.ld_views[LNV_TEXT].set_top(vis_line_t(0)); lnav_data.ld_rl_view->set_alt_value( HELP_MSG_2(f, F, "to switch to the next/previous file")); } if (!initial_build && lnav_data.ld_log_source.text_line_count() == 0 && !lnav_data.ld_other_files.empty()) { ensure_view(&lnav_data.ld_views[LNV_SCHEMA]); } if (!initial_build && lnav_data.ld_flags & LNF_HELP) { toggle_view(&lnav_data.ld_views[LNV_HELP]); initial_build = true; } if (lnav_data.ld_log_source.text_line_count() > 0 || lnav_data.ld_text_source.text_line_count() > 0 || !lnav_data.ld_other_files.empty()) { initial_build = true; } if (!session_loaded) { load_session(); if (!lnav_data.ld_session_file_names.empty()) { std::string ago; ago = time_ago(lnav_data.ld_session_save_time); lnav_data.ld_rl_view->set_value( ("restored session from " ANSI_BOLD_START) + ago + (ANSI_NORM "; press Ctrl-R to reset session")); } rebuild_indexes(true); session_loaded = true; } curr_to.tv_usec = 330000; { vector > msgs; execute_init_commands(msgs); if (!msgs.empty()) { pair last_msg = msgs.back(); lnav_data.ld_rl_view->set_value(last_msg.first); lnav_data.ld_rl_view->set_alt_value(last_msg.second); } } } else { if (FD_ISSET(STDIN_FILENO, &ready_rfds)) { static size_t escape_index = 0; static char escape_buffer[32]; int ch; while ((ch = getch()) != ERR) { alerter::singleton().new_input(ch); if (escape_index > sizeof(escape_buffer) - 1) { escape_index = 0; } else if (escape_index > 0) { escape_buffer[escape_index++] = ch; escape_buffer[escape_index] = '\0'; if (strcmp("\x1b[", escape_buffer) == 0) { lnav_data.ld_mouse.handle_mouse(ch); } else { for (size_t lpc = 0; lpc < escape_index; lpc++) { handle_key(escape_buffer[lpc]); } } escape_index = 0; continue; } switch (ch) { case CEOF: case KEY_RESIZE: break; case '\x1b': escape_index = 0; escape_buffer[escape_index++] = ch; escape_buffer[escape_index] = '\0'; break; case KEY_MOUSE: lnav_data.ld_mouse.handle_mouse(ch); break; default: handle_key(ch); break; } } } for (lpc = 0; lpc < LG__MAX; lpc++) { auto_ptr &gc = lnav_data.ld_grep_child[lpc]; if (gc.get() != NULL) { gc->get_grep_proc()->check_fd_set(ready_rfds); if (lpc == LG_GRAPH) { lnav_data.ld_views[LNV_GRAPH].reload_data(); /* XXX */ } } } for (lpc = 0; lpc < LNV__MAX; lpc++) { auto_ptr &gc = lnav_data.ld_search_child[lpc]; if (gc.get() != NULL) { gc->get_grep_proc()->check_fd_set(ready_rfds); if (!lnav_data.ld_view_stack.empty()) { lnav_data.ld_bottom_source. update_hits(lnav_data.ld_view_stack.top()); } } } rlc.check_fd_set(ready_rfds); } if (lnav_data.ld_winched) { struct winsize size; lnav_data.ld_winched = false; if (ioctl(fileno(stdout), TIOCGWINSZ, &size) == 0) { resizeterm(size.ws_row, size.ws_col); } rlc.window_change(); lnav_data.ld_status[0].window_change(); lnav_data.ld_status[1].window_change(); lnav_data.ld_view_stack.top()->set_needs_update(); } if (lnav_data.ld_child_terminated) { lnav_data.ld_child_terminated = false; for (std::list::iterator iter = lnav_data.ld_children.begin(); iter != lnav_data.ld_children.end(); ++iter) { int rc, child_stat; rc = waitpid(*iter, &child_stat, WNOHANG); if (rc == -1 || rc == 0) continue; iter = lnav_data.ld_children.erase(iter); } for (std::list::iterator iter = lnav_data.ld_pipers.begin(); iter != lnav_data.ld_pipers.end(); ++iter) { if ((*iter)->has_exited()) { delete *iter; iter = lnav_data.ld_pipers.erase(iter); } } } } } catch (readline_curses::error & e) { log_error("error: %s", strerror(e.e_err)); } } class strace_log_table : public log_vtab_impl { public: strace_log_table() : log_vtab_impl("strace_log") {}; void get_columns(vector &cols) { cols.push_back(vtab_column("funcname", SQLITE_TEXT)); cols.push_back(vtab_column("args", SQLITE_TEXT)); cols.push_back(vtab_column("result", SQLITE_TEXT)); cols.push_back(vtab_column("duration", SQLITE_TEXT)); #if 0 cols.push_back(vtab_column("arg0", SQLITE_TEXT)); cols.push_back(vtab_column("arg1", SQLITE_TEXT)); cols.push_back(vtab_column("arg2", SQLITE_TEXT)); cols.push_back(vtab_column("arg3", SQLITE_TEXT)); cols.push_back(vtab_column("arg4", SQLITE_TEXT)); cols.push_back(vtab_column("arg5", SQLITE_TEXT)); cols.push_back(vtab_column("arg6", SQLITE_TEXT)); cols.push_back(vtab_column("arg7", SQLITE_TEXT)); cols.push_back(vtab_column("arg8", SQLITE_TEXT)); cols.push_back(vtab_column("arg9", SQLITE_TEXT)); #endif }; #if 0 void extract(logfile *lf, const std::string &line, int column, sqlite3_context *ctx) { string function, args, result, duration = "0"; if (!this->slt_regex.FullMatch(line, &function, &args, &result, &duration)) { fprintf(stderr, "bad match! %s\n", line.c_str()); } switch (column) { case 0: sqlite3_result_text(ctx, function.c_str(), function.length(), SQLITE_TRANSIENT); break; case 1: sqlite3_result_text(ctx, result.c_str(), result.length(), SQLITE_TRANSIENT); break; case 2: sqlite3_result_text(ctx, duration.c_str(), duration.length(), SQLITE_TRANSIENT); break; default: { const char *arg_start = args.c_str(); int in_struct = 0, in_list = 0; int lpc, argnum, curarg = 0; bool in_quote = false; argnum = column - 3; for (lpc = 0; lpc < (int)args.length(); lpc++) { switch (args[lpc]) { case '{': if (!in_quote) { in_struct += 1; } break; case '}': if (!in_quote) { in_struct -= 1; } break; case '[': if (!in_quote) { in_list += 1; } break; case ']': if (!in_quote) { in_list -= 1; } break; case '"': if (!in_quote) { in_quote = true; } else if (lpc > 0 && args[lpc - 1] != '\\') { in_quote = false; } break; case ',': if (!in_quote && !in_struct && !in_list) { if (curarg == argnum) { sqlite3_result_text(ctx, arg_start, &(args.c_str()[lpc]) - arg_start, SQLITE_TRANSIENT); return; } curarg += 1; arg_start = &(args.c_str()[lpc + 1]); } break; } } if (curarg == argnum) { sqlite3_result_text(ctx, arg_start, &(args.c_str()[lpc]) - arg_start, SQLITE_TRANSIENT); } else { sqlite3_result_text(ctx, "", 0, SQLITE_TRANSIENT); } } break; } }; private: pcrecpp::RE slt_regex; #endif }; static void setup_highlights(textview_curses::highlight_map_t &hm) { hm["$kw"] = textview_curses::highlighter(xpcre_compile( "(?:" "\\balter |" "\\band\\b|" "\\bas |" "\\bbetween\\b|" "\\bbool\\b|" "\\bboolean\\b|" "\\bbreak\\b|" "\\bcase\\b|" "\\bcatch\\b|" "\\bchar\\b|" "\\bclass\\b|" "\\bcollate\\b|" "\\bconst\\b|" "\\bcontinue\\b|" "\\bcreate\\s+(?:virtual)?|" "\\bdatetime\\b|" "\\bdef |" "\\bdefault[:\\s]|" "\\bdo\\b|" "\\bdone\\b|" "\\bdouble\\b|" "\\bdrop\\b|" "\\belif |" "\\belse\\b|" "\\benum\\b|" "\\bendif\\b|" "\\besac\\b|" "\\bexcept[\\s:]|" "\\bexists\\b|" "\\bexport\\b|" "\\bextends\\b|" "\\bextern\\b|" "\\bfalse\\b|" "\\bfi\\b|" "\\bfloat\\b|" "\\bfor\\b|" "\\bforeign\\s+key\\b|" "\\bfrom |" "\\bgoto\\b|" "\\bgroup by |" "\\bif\\b|" "\\bimport |" "\\bimplements\\b|" "\\bin\\b|" "\\binline\\b|" "\\binner\\b|" "\\binsert |" "\\bint\\b|" "\\binto\\b|" "\\binterface\\b|" "\\bjoin\\b|" "\\blambda\\b|" "\\blet\\b|" "\\blong\\b|" "\\bnamespace\\b|" "\\bnew\\b|" "\\bnot\\b|" "\\bnull\\b|" "\\boperator\\b|" "\\bor\\b|" "\\border by |" "\\bpackage\\b|" "\\bprimary\\s+key\\b|" "\\bprivate\\b|" "\\bprotected\\b|" "\\bpublic\\b|" "\\braise\\b|" "\\breferences\\b|" "\\b(?=]+)[^>]*>")); hm["$stringd"] = textview_curses:: highlighter(xpcre_compile("\"(?:\\\\.|[^\"])*\""), false, view_colors::VCR_STRING); hm["$strings"] = textview_curses:: highlighter(xpcre_compile( "(? loader_errors; int lpc, c, retval = EXIT_SUCCESS; auto_ptr stdin_reader; const char * stdin_out = NULL; setlocale(LC_NUMERIC, ""); rl_readline_name = "lnav"; ensure_dotlnav(); log_install_handlers(); lnav_data.ld_debug_log_name = "/dev/null"; while ((c = getopt(argc, argv, "hHarsCc:I:f:d:nqtw:V")) != -1) { switch (c) { case 'h': usage(); exit(retval); break; case 'H': lnav_data.ld_flags |= LNF_HELP; break; case 'C': lnav_data.ld_flags |= LNF_CHECK_CONFIG; break; case 'c': switch (optarg[0]) { case ':': case '/': case ';': case '|': break; default: fprintf(stderr, "error: command arguments should start with a " "colon, semi-colon, or pipe-symbol to denote:\n"); fprintf(stderr, "error: a built-in command, SQL query, " "or a file path that contains commands to execute\n"); usage(); exit(EXIT_FAILURE); break; } lnav_data.ld_commands.push_back(optarg); break; case 'f': if (access(optarg, R_OK) != 0) { perror("invalid command file"); exit(EXIT_FAILURE); } lnav_data.ld_commands.push_back("|" + string(optarg)); break; case 'I': if (access(optarg, X_OK) != 0) { perror("invalid config path"); exit(EXIT_FAILURE); } lnav_data.ld_config_paths.push_back(optarg); break; case 'd': lnav_data.ld_debug_log_name = optarg; break; case 'a': lnav_data.ld_flags |= LNF__ALL; break; case 'n': lnav_data.ld_flags |= LNF_HEADLESS; break; case 'q': lnav_data.ld_flags |= LNF_QUIET; break; case 'r': lnav_data.ld_flags |= LNF_ROTATED; break; case 's': lnav_data.ld_flags |= LNF_SYSLOG; break; case 't': lnav_data.ld_flags |= LNF_TIMESTAMP; break; case 'w': stdin_out = optarg; break; case 'V': printf("%s\n", PACKAGE_STRING); exit(0); break; default: retval = EXIT_FAILURE; break; } } argc -= optind; argv += optind; lnav_log_file = fopen(lnav_data.ld_debug_log_name, "a"); load_formats(lnav_data.ld_config_paths, loader_errors); if (!loader_errors.empty()) { for (std::vector::iterator iter = loader_errors.begin(); iter != loader_errors.end(); ++iter) { fprintf(stderr, "%s%s", iter->c_str(), (*iter)[iter->size() - 1] == '\n' ? "" : "\n"); } return EXIT_FAILURE; } if (lnav_data.ld_flags & LNF_CHECK_CONFIG) { return EXIT_SUCCESS; } /* If we statically linked against an ncurses library that had a non- * standard path to the terminfo database, we need to set this variable * so that it will try the default path. */ setenv("TERMINFO_DIRS", "/usr/share/terminfo:/lib/terminfo:/usr/share/lib/terminfo", 0); if (sqlite3_open(":memory:", lnav_data.ld_db.out()) != SQLITE_OK) { fprintf(stderr, "error: unable to create sqlite memory database\n"); exit(EXIT_FAILURE); } { int register_collation_functions(sqlite3 * db); register_sqlite_funcs(lnav_data.ld_db.in(), sqlite_registration_funcs); register_collation_functions(lnav_data.ld_db.in()); } lnav_data.ld_program_name = argv[0]; lnav_data.ld_vtab_manager = new log_vtab_manager(lnav_data.ld_db, lnav_data.ld_views[LNV_LOG], lnav_data.ld_log_source, sql_progress); { auto_mem errmsg; if (sqlite3_exec(lnav_data.ld_db.in(), init_sql, NULL, NULL, errmsg.out()) != SQLITE_OK) { fprintf(stderr, "error: unable to execute DB init -- %s\n", errmsg.in()); } } lnav_data.ld_vtab_manager->register_vtab(new log_vtab_impl("generic_log")); lnav_data.ld_vtab_manager->register_vtab(new strace_log_table()); for (std::vector::iterator iter = log_format::get_root_formats().begin(); iter != log_format::get_root_formats().end(); ++iter) { log_vtab_impl *lvi = (*iter)->get_vtab_impl(); if (lvi != NULL) { lnav_data.ld_vtab_manager->register_vtab(lvi); } } DEFAULT_FILES.insert(make_pair(LNF_SYSLOG, string("var/log/messages"))); DEFAULT_FILES.insert(make_pair(LNF_SYSLOG, string("var/log/system.log"))); DEFAULT_FILES.insert(make_pair(LNF_SYSLOG, string("var/log/syslog"))); DEFAULT_FILES.insert(make_pair(LNF_SYSLOG, string("var/log/syslog.log"))); init_lnav_commands(lnav_commands); lnav_data.ld_log_source.add_filter(&lnav_data.ld_level_filter); lnav_data.ld_views[LNV_HELP]. set_sub_source(new plain_text_source(help_txt)); lnav_data.ld_views[LNV_HELP].set_word_wrap(true); lnav_data.ld_views[LNV_LOG]. set_sub_source(&lnav_data.ld_log_source); lnav_data.ld_views[LNV_LOG]. set_delegate(new action_delegate(lnav_data.ld_log_source)); lnav_data.ld_views[LNV_TEXT]. set_sub_source(&lnav_data.ld_text_source); lnav_data.ld_views[LNV_HISTOGRAM]. set_sub_source(&lnav_data.ld_hist_source); lnav_data.ld_views[LNV_GRAPH]. set_sub_source(&lnav_data.ld_graph_source); lnav_data.ld_views[LNV_DB]. set_sub_source(&lnav_data.ld_db_source); lnav_data.ld_db_overlay.dos_labels = &lnav_data.ld_db_rows; lnav_data.ld_views[LNV_DB]. set_overlay_source(&lnav_data.ld_db_overlay); lnav_data.ld_views[LNV_LOG]. set_overlay_source(new field_overlay_source(lnav_data.ld_log_source)); lnav_data.ld_db_overlay.dos_hist_source = &lnav_data.ld_db_source; lnav_data.ld_match_view.set_left(0); for (int lpc = 0; lpc < LNV__MAX; lpc++) { lnav_data.ld_views[lpc].set_gutter_source(new log_gutter_source()); } { setup_highlights(lnav_data.ld_views[LNV_LOG].get_highlights()); setup_highlights(lnav_data.ld_views[LNV_TEXT].get_highlights()); setup_highlights(lnav_data.ld_views[LNV_SCHEMA].get_highlights()); } { hist_source &hs = lnav_data.ld_hist_source; lnav_data.ld_hist_zoom = 2; hs.set_role_for_type(bucket_type_t(logline::LEVEL_FATAL), view_colors::VCR_ERROR); hs.set_role_for_type(bucket_type_t(logline::LEVEL_CRITICAL), view_colors::VCR_ERROR); hs.set_role_for_type(bucket_type_t(logline::LEVEL_ERROR), view_colors::VCR_ERROR); hs.set_role_for_type(bucket_type_t(logline::LEVEL_WARNING), view_colors::VCR_WARNING); hs.set_label_source(new time_label_source()); } { hist_source &hs = lnav_data.ld_graph_source; hs.set_bucket_size(1); hs.set_group_size(100); } { hist_source &hs = lnav_data.ld_db_source; hs.set_bucket_size(1); hs.set_group_size(10); hs.set_label_source(&lnav_data.ld_db_rows); } for (int lpc = 0; lpc < LNV__MAX; lpc++) { lnav_data.ld_views[lpc].set_title(view_titles[lpc]); } lnav_data.ld_looping = true; lnav_data.ld_mode = LNM_PAGING; if (isatty(STDIN_FILENO) && argc == 0 && !(lnav_data.ld_flags & LNF__ALL)) { lnav_data.ld_flags |= LNF_SYSLOG; } if (lnav_data.ld_flags != 0) { char start_dir[FILENAME_MAX]; if (getcwd(start_dir, sizeof(start_dir)) == NULL) { perror("getcwd"); } else { do { for (lpc = 0; lpc < LNB__MAX; lpc++) { if (!append_default_files((lnav_flags_t)(1L << lpc))) { retval = EXIT_FAILURE; } } } while (lnav_data.ld_file_names.empty() && change_to_parent_dir()); if (chdir(start_dir) == -1) { perror("chdir(start_dir)"); } } } for (lpc = 0; lpc < argc; lpc++) { auto_mem abspath; struct stat st; if (is_glob(argv[lpc])) { lnav_data.ld_file_names.insert(make_pair(argv[lpc], -1)); } else if (stat(argv[lpc], &st) == -1) { fprintf(stderr, "Cannot stat file: %s -- %s\n", argv[lpc], strerror(errno)); retval = EXIT_FAILURE; } else if ((abspath = realpath(argv[lpc], NULL)) == NULL) { perror("Cannot find file"); retval = EXIT_FAILURE; } else if (S_ISDIR(st.st_mode)) { string dir_wild(abspath.in()); if (dir_wild[dir_wild.size() - 1] == '/') { dir_wild.resize(dir_wild.size() - 1); } lnav_data.ld_file_names.insert(make_pair(dir_wild + "/*", -1)); } else { lnav_data.ld_file_names.insert(make_pair(abspath.in(), -1)); } } if (!(lnav_data.ld_flags & LNF_HEADLESS) && !isatty(STDOUT_FILENO)) { fprintf(stderr, "error: stdout is not a tty.\n"); retval = EXIT_FAILURE; } if (!isatty(STDIN_FILENO)) { stdin_reader = auto_ptr(new piper_proc(STDIN_FILENO, lnav_data.ld_flags & LNF_TIMESTAMP, stdin_out)); lnav_data.ld_file_names.insert(make_pair("stdin", stdin_reader->get_fd())); if (dup2(STDOUT_FILENO, STDIN_FILENO) == -1) { perror("cannot dup stdout to stdin"); } } if (lnav_data.ld_file_names.empty() && !lnav_data.ld_flags & LNF_HELP) { fprintf(stderr, "error: no log files given/found.\n"); retval = EXIT_FAILURE; } if (retval != EXIT_SUCCESS) { usage(); } else { try { rescan_files(true); log_info("startup: %s", PACKAGE_STRING); log_host_info(); log_info("lnav_data:"); log_info(" flags=%x", lnav_data.ld_flags); log_info(" commands:"); for (std::list::iterator cmd_iter = lnav_data.ld_commands.begin(); cmd_iter != lnav_data.ld_commands.end(); ++cmd_iter) { log_info(" %s", cmd_iter->c_str()); } log_info(" files:"); for (std::set >::iterator file_iter = lnav_data.ld_file_names.begin(); file_iter != lnav_data.ld_file_names.end(); ++file_iter) { log_info(" %s", file_iter->first.c_str()); } if (lnav_data.ld_flags & LNF_HEADLESS) { std::vector > msgs; std::vector >::iterator msg_iter; textview_curses *tc; attr_line_t al; const std::string &line = al.get_string(); bool found_error = false; alerter::singleton().enabled(false); lnav_data.ld_view_stack.push(&lnav_data.ld_views[LNV_LOG]); rebuild_indexes(true); lnav_data.ld_views[LNV_LOG].set_top(vis_line_t(0)); execute_init_commands(msgs); rebuild_indexes(false); for (msg_iter = msgs.begin(); msg_iter != msgs.end(); ++msg_iter) { if (strncmp("error:", msg_iter->first.c_str(), 6) != 0) { continue; } fprintf(stderr, "%s\n", msg_iter->first.c_str()); found_error = true; } if (!found_error && !(lnav_data.ld_flags & LNF_QUIET) && !lnav_data.ld_view_stack.empty() && !lnav_data.ld_stdout_used) { bool suppress_empty_lines = false; list_overlay_source *los; vis_line_t y; tc = lnav_data.ld_view_stack.top(); if (tc == &lnav_data.ld_views[LNV_DB]) { suppress_empty_lines = true; } los = tc->get_overlay_source(); for (vis_line_t vl = tc->get_top(); vl < tc->get_inner_height(); ++vl, ++y) { while (los != NULL && los->list_value_for_overlay(*tc, y, al)) { printf("%s\n", line.c_str()); ++y; } tc->listview_value_for_row(*tc, vl, al); if (suppress_empty_lines && line.empty()) { continue; } printf("%s\n", line.c_str()); } } } else { init_session(); log_info(" session_id=%s", lnav_data.ld_session_id.c_str()); scan_sessions(); guard_termios gt(STDIN_FILENO); lnav_log_orig_termios = gt.get_termios(); looper(); save_session(); } } catch (line_buffer::error & e) { fprintf(stderr, "error: %s\n", strerror(e.e_err)); } catch (logfile::error & e) { if (e.e_err != EINTR) { fprintf(stderr, "error: %s -- '%s'\n", strerror(e.e_err), e.e_filename.c_str()); } } // When reading from stdin, dump out the last couple hundred lines so // the user can have the text in their terminal history. if (stdin_reader.get() != NULL) { list::iterator file_iter; struct stat st; fstat(stdin_reader->get_fd(), &st); file_iter = find_if(lnav_data.ld_files.begin(), lnav_data.ld_files.end(), same_file(st)); if (file_iter != lnav_data.ld_files.end()) { logfile::iterator line_iter; logfile *lf = *file_iter; string str; for (line_iter = lf->begin(); line_iter != lf->end(); ++line_iter) { lf->read_line(line_iter, str); write(STDOUT_FILENO, str.c_str(), str.size()); write(STDOUT_FILENO, "\n", 1); } } } } return retval; } lnav-0.7.0/src/lnav.hh000664 000765 000024 00000017544 12311270204 015003 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file lnav.hh */ #ifndef __lnav_hh #define __lnav_hh #include "config.h" #include #include #include #include #include #include #include "byte_array.hh" #include "grapher.hh" #include "logfile.hh" #include "hist_source.hh" #include "statusview_curses.hh" #include "listview_curses.hh" #include "top_status_source.hh" #include "bottom_status_source.hh" #include "grep_highlighter.hh" #include "db_sub_source.hh" #include "textfile_sub_source.hh" #include "log_vtab_impl.hh" #include "readline_curses.hh" #include "xterm_mouse.hh" #include "piper_proc.hh" #include "term_extra.hh" #include "ansi_scrubber.hh" /** The command modes that are available while viewing a file. */ typedef enum { LNM_PAGING, LNM_COMMAND, LNM_SEARCH, LNM_CAPTURE, LNM_SQL, } ln_mode_t; enum { LNB_SYSLOG, LNB__MAX, LNB_TIMESTAMP, LNB_HELP, LNB_HEADLESS, LNB_QUIET, LNB_ROTATED, LNB_CHECK_CONFIG, }; /** Flags set on the lnav command-line. */ typedef enum { LNF_SYSLOG = (1L << LNB_SYSLOG), LNF_ROTATED = (1L << LNB_ROTATED), LNF_TIMESTAMP = (1L << LNB_TIMESTAMP), LNF_HELP = (1L << LNB_HELP), LNF_HEADLESS = (1L << LNB_HEADLESS), LNF_QUIET = (1L << LNB_QUIET), LNF_CHECK_CONFIG = (1L << LNB_CHECK_CONFIG), LNF__ALL = (LNF_SYSLOG|LNF_HELP) } lnav_flags_t; /** The different views available. */ typedef enum { LNV_LOG, LNV_TEXT, LNV_HELP, LNV_HISTOGRAM, LNV_GRAPH, LNV_DB, LNV_EXAMPLE, LNV_SCHEMA, LNV__MAX } lnav_view_t; extern const char *lnav_view_strings[LNV__MAX + 1]; /** The status bars. */ typedef enum { LNS_TOP, LNS_BOTTOM, LNS__MAX } lnav_status_t; typedef enum { LG_GRAPH, LG_CAPTURE, LG__MAX } lnav_grep_t; void sqlite_close_wrapper(void *mem); typedef std::pair ppid_time_pair_t; typedef std::pair session_pair_t; class level_filter : public logfile_filter { public: level_filter() : logfile_filter(EXCLUDE, ""), lf_min_level(logline::LEVEL_UNKNOWN) { }; bool matches(const logline &ll, const std::string &line) { return (ll.get_level() & ~logline::LEVEL__FLAGS) < this->lf_min_level; }; std::string to_command(void) { return ("set-min-log-level " + std::string(logline::level_names[this->lf_min_level])); }; logline::level_t lf_min_level; }; struct _lnav_data { std::string ld_session_id; time_t ld_session_time; time_t ld_session_load_time; time_t ld_session_save_time; std::list ld_session_file_names; int ld_session_file_index; const char * ld_program_name; const char * ld_debug_log_name; std::list ld_commands; std::vector ld_config_paths; std::set > ld_file_names; std::list ld_files; std::list ld_other_files; std::list > ld_files_to_front; bool ld_stdout_used; sig_atomic_t ld_looping; sig_atomic_t ld_winched; sig_atomic_t ld_child_terminated; unsigned long ld_flags; WINDOW * ld_window; ln_mode_t ld_mode; statusview_curses ld_status[LNS__MAX]; top_status_source ld_top_source; bottom_status_source ld_bottom_source; listview_curses::action::broadcaster ld_scroll_broadcaster; time_t ld_top_time; int ld_top_time_millis; time_t ld_bottom_time; int ld_bottom_time_millis; textview_curses ld_match_view; std::stack ld_view_stack; textview_curses ld_views[LNV__MAX]; std::auto_ptr ld_search_child[LNV__MAX]; vis_line_t ld_search_start_line; readline_curses * ld_rl_view; level_filter ld_level_filter; logfile_sub_source ld_log_source; hist_source ld_hist_source; int ld_hist_zoom; textfile_sub_source ld_text_source; std::map ld_last_user_mark; grapher ld_graph_source; hist_source ld_db_source; db_label_source ld_db_rows; db_overlay_source ld_db_overlay; std::vector ld_db_key_names; int ld_max_fd; fd_set ld_read_fds; std::auto_ptr ld_grep_child[LG__MAX]; std::string ld_previous_search; std::string ld_last_search[LNV__MAX]; log_vtab_manager * ld_vtab_manager; auto_mem ld_db; std::list ld_children; std::list ld_pipers; xterm_mouse ld_mouse; term_extra ld_term_extra; }; extern struct _lnav_data lnav_data; #define HELP_MSG_1(x, msg) \ "Press '" ANSI_BOLD(#x) "' " msg #define HELP_MSG_2(x, y, msg) \ "Press " ANSI_BOLD(#x) "/" ANSI_BOLD(#y) " " msg void rebuild_indexes(bool force); void ensure_view(textview_curses *expected_tc); bool toggle_view(textview_curses *toggle_tc); std::string execute_command(std::string cmdline); bool setup_logline_table(); int sql_callback(sqlite3_stmt *stmt); void execute_search(lnav_view_t view, const std::string ®ex); void redo_search(lnav_view_t view_index); #endif lnav-0.7.0/src/lnav_commands.cc000664 000765 000024 00000123745 12313212124 016652 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include "lnav.hh" #include "lnav_config.hh" #include "lnav_util.hh" #include "auto_mem.hh" #include "log_data_table.hh" #include "lnav_commands.hh" #include "session_data.hh" using namespace std; static bool wordexperr(int rc, string &msg) { switch (rc) { case WRDE_BADCHAR: msg = "error: invalid filename character"; return false; case WRDE_CMDSUB: msg = "error: command substitution is not allowed"; return false; case WRDE_BADVAL: msg = "error: unknown environment variable in file name"; return false; case WRDE_NOSPACE: msg = "error: out of memory"; return false; case WRDE_SYNTAX: msg = "error: invalid syntax"; return false; default: break; } return true; } static string com_adjust_log_time(string cmdline, vector &args) { string retval = "error: expecting new time value"; if (args.size() == 0) { args.push_back("line-time"); } else if (lnav_data.ld_views[LNV_LOG].get_inner_height() == 0) { retval = "error: no log messages"; } else if (args.size() >= 2) { logfile_sub_source &lss = lnav_data.ld_log_source; struct timeval top_time, time_diff; struct timeval new_time = { 0, 0 }; content_line_t top_content; date_time_scanner dts; vis_line_t top_line; struct tm tm; logfile *lf; top_line = lnav_data.ld_views[LNV_LOG].get_top(); top_content = lss.at(top_line); lf = lss.find(top_content); logline &ll = (*lf)[top_content]; top_time = ll.get_timeval(); dts.set_base_time(top_time.tv_sec); args[1] = cmdline.substr(cmdline.find(args[1], args[0].size())); if (dts.scan(args[1].c_str(), NULL, &tm, new_time) != NULL) { timersub(&new_time, &top_time, &time_diff); lf->adjust_content_time(top_content, time_diff, false); rebuild_indexes(true); retval = "info: adjusted time"; } } return retval; } static string com_unix_time(string cmdline, vector &args) { string retval = "error: expecting a unix time value"; if (args.size() == 0) { } else if (args.size() >= 2) { char ftime[128] = ""; bool parsed = false; struct tm log_time; time_t u_time; size_t millis; char * rest; u_time = time(NULL); log_time = *localtime(&u_time); log_time.tm_isdst = -1; args[1] = cmdline.substr(cmdline.find(args[1], args[0].size())); if ((millis = args[1].find('.')) != string::npos || (millis = args[1].find(',')) != string::npos) { args[1] = args[1].erase(millis, 4); } if (((rest = strptime(args[1].c_str(), "%b %d %H:%M:%S %Y", &log_time)) != NULL && (rest - args[1].c_str()) >= 20) || ((rest = strptime(args[1].c_str(), "%Y-%m-%d %H:%M:%S", &log_time)) != NULL && (rest - args[1].c_str()) >= 19)) { u_time = mktime(&log_time); parsed = true; } else if (sscanf(args[1].c_str(), "%ld", &u_time)) { log_time = *localtime(&u_time); parsed = true; } if (parsed) { int len; strftime(ftime, sizeof(ftime), "%a %b %d %H:%M:%S %Y %z %Z", localtime(&u_time)); len = strlen(ftime); snprintf(ftime + len, sizeof(ftime) - len, " -- %ld\n", u_time); retval = string(ftime); } } return retval; } static string com_current_time(string cmdline, vector &args) { char ftime[128]; struct tm localtm; string retval; time_t u_time; int len; memset(&localtm, 0, sizeof(localtm)); u_time = time(NULL); strftime(ftime, sizeof(ftime), "%a %b %d %H:%M:%S %Y %z %Z", localtime_r(&u_time, &localtm)); len = strlen(ftime); snprintf(ftime + len, sizeof(ftime) - len, " -- %ld\n", u_time); retval = string(ftime); return retval; } static string com_goto(string cmdline, vector &args) { string retval = "error: expecting line number/percentage or timestamp"; if (args.size() == 0) { args.push_back("line-time"); } else if (args.size() > 1) { textview_curses *tc = lnav_data.ld_view_stack.top(); int line_number, consumed; date_time_scanner dts; struct timeval tv; struct tm tm; float value; if (dts.scan(args[1].c_str(), NULL, &tm, tv) != NULL) { if (tc == &lnav_data.ld_views[LNV_LOG]) { vis_line_t vl; vl = lnav_data.ld_log_source.find_from_time(tv); tc->set_top(vl); retval = ""; } else { retval = "error: time values only work in the log view"; } } else if (sscanf(args[1].c_str(), "%f%n", &value, &consumed) == 1) { if (args[1][consumed] == '%') { line_number = (int) ((double)tc->get_inner_height() * (value / 100.0)); } else { line_number = (int)value; if (line_number < 0) { line_number = tc->get_inner_height() + line_number; } } tc->set_top(vis_line_t(line_number)); retval = ""; } } return retval; } static bool csv_needs_quoting(const string &str) { return (str.find_first_of(",\"") != string::npos); } static string csv_quote_string(const string &str) { static pcrecpp::RE csv_column_quoter("\""); string retval = str; csv_column_quoter.GlobalReplace("\"\"", &retval); retval.insert(0, 1, '\"'); retval.append(1, '\"'); return retval; } static void csv_write_string(FILE *outfile, const string &str) { if (csv_needs_quoting(str)) { string quoted_str = csv_quote_string(str); fprintf(outfile, "%s", quoted_str.c_str()); } else { fprintf(outfile, "%s", str.c_str()); } } static void yajl_writer(void *context, const char *str, size_t len) { FILE *file = (FILE *)context; fwrite(str, len, 1, file); } static void json_write_row(yajl_gen handle, int row) { db_label_source &dls = lnav_data.ld_db_rows; yajlpp_map obj_map(handle); for (int col = 0; col < dls.dls_column_types.size(); col++) { obj_map.gen(dls.dls_headers[col]); if (dls.dls_rows[row][col] == db_label_source::NULL_STR) { obj_map.gen(); continue; } switch (dls.dls_column_types[col]) { case SQLITE_FLOAT: case SQLITE_INTEGER: yajl_gen_number(handle, dls.dls_rows[row][col], strlen(dls.dls_rows[row][col])); break; default: obj_map.gen(dls.dls_rows[row][col]); break; } } } static string com_save_to(string cmdline, vector &args) { FILE * outfile = NULL; const char *mode = ""; string fn, retval; if (args.size() == 0) { args.push_back("filename"); return ""; } if (args.size() < 2) { return "error: expecting file name"; } fn = trim(cmdline.substr(cmdline.find(args[1], args[0].size()))); static_root_mem wordmem; int rc = wordexp(fn.c_str(), wordmem.inout(), WRDE_NOCMD | WRDE_UNDEF); if (!wordexperr(rc, retval)) { return retval; } if (wordmem->we_wordc > 1) { return "error: more than one file name was matched"; } if (args[0] == "append-to") { mode = "a"; } else { mode = "w"; } textview_curses * tc = lnav_data.ld_view_stack.top(); bookmark_vector &bv = tc->get_bookmarks()[&textview_curses::BM_USER]; db_label_source &dls = lnav_data.ld_db_rows; if (args[0] == "write-csv-to" || args[0] == "write-json-to") { if (dls.dls_headers.empty()) { return "error: no query result to write, use ';' to execute a query"; } } else { if (bv.empty()) { return "error: no lines marked to write, use 'm' to mark lines"; } } if (strcmp(wordmem->we_wordv[0], "-") == 0) { if (!(lnav_data.ld_flags & LNF_HEADLESS)) { return "error: writing to stdout is only available in headless mode"; } outfile = stdout; lnav_data.ld_stdout_used = true; } else if ((outfile = fopen(wordmem->we_wordv[0], mode)) == NULL) { return "error: unable to open file -- " + string(wordmem->we_wordv[0]); } if (args[0] == "write-csv-to") { std::vector >::iterator row_iter; std::vector::iterator iter; std::vector::iterator hdr_iter; bool first = true; for (hdr_iter = dls.dls_headers.begin(); hdr_iter != dls.dls_headers.end(); ++hdr_iter) { if (!first) { fprintf(outfile, ","); } csv_write_string(outfile, *hdr_iter); first = false; } fprintf(outfile, "\n"); for (row_iter = dls.dls_rows.begin(); row_iter != dls.dls_rows.end(); ++row_iter) { first = true; for (iter = row_iter->begin(); iter != row_iter->end(); ++iter) { if (!first) { fprintf(outfile, ","); } csv_write_string(outfile, *iter); first = false; } fprintf(outfile, "\n"); } } else if (args[0] == "write-json-to") { yajl_gen handle = NULL; if ((handle = yajl_gen_alloc(NULL)) == NULL) { return "error: unable to allocate memory"; } else { yajl_gen_config(handle, yajl_gen_beautify, 1); yajl_gen_config(handle, yajl_gen_print_callback, yajl_writer, outfile); { yajlpp_array root_array(handle); for (int row = 0; row < dls.dls_rows.size(); row++) { json_write_row(handle, row); } } } } else { bookmark_vector::iterator iter; string line; for (iter = bv.begin(); iter != bv.end(); iter++) { tc->grep_value_for_line(*iter, line); fprintf(outfile, "%s\n", line.c_str()); } } if (outfile != stdout) { fclose(outfile); } outfile = NULL; return ""; } static string com_highlight(string cmdline, vector &args) { string retval = "error: expecting regular expression to highlight"; if (args.size() == 0) { } else if (args.size() > 1) { textview_curses *tc = lnav_data.ld_view_stack.top(); textview_curses::highlight_map_t &hm = tc->get_highlights(); const char *errptr; pcre * code; int eoff; args[1] = cmdline.substr(cmdline.find(args[1], args[0].size())); if (hm.find(args[1]) != hm.end()) { retval = "error: highlight already exists"; } else if ((code = pcre_compile(args[1].c_str(), PCRE_CASELESS, &errptr, &eoff, NULL)) == NULL) { retval = "error: " + string(errptr); } else { textview_curses::highlighter hl(code, false); hm[args[1]] = hl; retval = "info: highlight pattern now active"; } } return retval; } static string com_graph(string cmdline, vector &args) { string retval = "error: expecting regular expression to graph"; if (args.size() == 0) { args.push_back("graph"); } else if (args.size() > 1) { const char *errptr; pcre * code; int eoff; args[1] = cmdline.substr(cmdline.find(args[1], args[0].size())); if ((code = pcre_compile(args[1].c_str(), PCRE_CASELESS, &errptr, &eoff, NULL)) == NULL) { retval = "error: " + string(errptr); } else { textview_curses & tc = lnav_data.ld_views[LNV_LOG]; textview_curses::highlighter hl(code, true); textview_curses::highlight_map_t &hm = tc.get_highlights(); hm["(graph"] = hl; lnav_data.ld_graph_source.set_highlighter(&hm["(graph"]); auto_ptr gp(new grep_proc(code, tc, lnav_data.ld_max_fd, lnav_data.ld_read_fds)); gp->queue_request(); gp->start(); gp->set_sink(&lnav_data.ld_graph_source); auto_ptr gh(new grep_highlighter(gp, "(graph", hm)); lnav_data.ld_grep_child[LG_GRAPH] = gh; toggle_view(&lnav_data.ld_views[LNV_GRAPH]); retval = ""; } } return retval; } static string com_help(string cmdline, vector &args) { string retval = ""; if (args.size() == 0) {} else { ensure_view(&lnav_data.ld_views[LNV_HELP]); } return retval; } class pcre_filter : public logfile_filter { public: pcre_filter(type_t type, const string id, pcre *code) : logfile_filter(type, id), pf_pcre(code) { }; virtual ~pcre_filter() { }; bool matches(const logline &ll, const string &line) { pcre_context_static<30> pc; pcre_input pi(line); return this->pf_pcre.match(pc, pi); }; std::string to_command(void) { return (this->lf_type == logfile_filter::INCLUDE ? "filter-in " : "filter-out ") + this->lf_id; }; protected: pcrepp pf_pcre; }; static string com_filter(string cmdline, vector &args) { string retval = "error: expecting regular expression to filter out"; if (args.size() == 0) { args.push_back("filter"); } else if (args.size() > 1) { logfile_sub_source &lss = lnav_data.ld_log_source; const char *errptr; pcre * code; int eoff; args[1] = cmdline.substr(cmdline.find(args[1], args[0].size())); if (lss.get_filter(args[1]) != NULL) { retval = "error: filter already exists"; } else if ((code = pcre_compile(args[1].c_str(), PCRE_CASELESS, &errptr, &eoff, NULL)) == NULL) { retval = "error: " + string(errptr); } else { logfile_filter::type_t lt = (args[0] == "filter-out") ? logfile_filter::EXCLUDE : logfile_filter::INCLUDE; auto_ptr pf(new pcre_filter(lt, args[1], code)); lss.add_filter(pf.release()); if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->add_possibility( LNM_COMMAND, "enabled-filter", args[1]); } rebuild_indexes(true); retval = "info: filter now active"; } } return retval; } static string com_enable_filter(string cmdline, vector &args) { string retval = "error: expecting disabled filter to enable"; if (args.size() == 0) { args.push_back("disabled-filter"); } else if (args.size() > 1) { logfile_filter *lf; args[1] = cmdline.substr(cmdline.find(args[1], args[0].size())); lf = lnav_data.ld_log_source.get_filter(args[1]); if (lf == NULL) { retval = "error: no such filter -- " + args[1]; } else if (lf->is_enabled()) { retval = "info: filter already enabled"; } else { lnav_data.ld_log_source.set_filter_enabled(lf, true); if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->rem_possibility( LNM_COMMAND, "disabled-filter", args[1]); lnav_data.ld_rl_view->add_possibility( LNM_COMMAND, "enabled-filter", args[1]); } rebuild_indexes(true); retval = "info: filter enabled"; } } return retval; } static string com_disable_filter(string cmdline, vector &args) { string retval = "error: expecting enabled filter to disable"; if (args.size() == 0) { args.push_back("enabled-filter"); } else if (args.size() > 1) { logfile_filter *lf; args[1] = cmdline.substr(cmdline.find(args[1], args[0].size())); lf = lnav_data.ld_log_source.get_filter(args[1]); if (lf == NULL) { retval = "error: no such filter -- " + args[1]; } else if (!lf->is_enabled()) { retval = "info: filter already disabled"; } else { lnav_data.ld_log_source.set_filter_enabled(lf, false); if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->rem_possibility( LNM_COMMAND, "disabled-filter", args[1]); lnav_data.ld_rl_view->add_possibility( LNM_COMMAND, "enabled-filter", args[1]); } rebuild_indexes(true); retval = "info: filter disabled"; } } return retval; } static string com_enable_word_wrap(string cmdline, vector &args) { string retval = ""; if (args.size() == 0) { } else { lnav_data.ld_views[LNV_LOG].set_word_wrap(true); lnav_data.ld_views[LNV_LOG].set_needs_update(); lnav_data.ld_views[LNV_TEXT].set_word_wrap(true); lnav_data.ld_views[LNV_TEXT].set_needs_update(); } return retval; } static string com_disable_word_wrap(string cmdline, vector &args) { string retval = ""; if (args.size() == 0) { } else { lnav_data.ld_views[LNV_LOG].set_word_wrap(false); lnav_data.ld_views[LNV_LOG].set_needs_update(); lnav_data.ld_views[LNV_TEXT].set_word_wrap(false); lnav_data.ld_views[LNV_TEXT].set_needs_update(); } return retval; } static std::vector custom_logline_tables; static string com_create_logline_table(string cmdline, vector &args) { string retval = "error: expecting a table name"; if (args.size() == 0) {} else if (args.size() == 2) { textview_curses &log_view = lnav_data.ld_views[LNV_LOG]; if (log_view.get_inner_height() == 0) { retval = "error: no log data available"; } else { vis_line_t vl = log_view.get_top(); content_line_t cl = lnav_data.ld_log_source.at_base(vl); log_data_table *ldt = new log_data_table(cl, args[1]); string errmsg; errmsg = lnav_data.ld_vtab_manager->register_vtab(ldt); if (errmsg.empty()) { if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->add_possibility(LNM_COMMAND, "custom-table", args[1]); } retval = "info: created new log table -- " + args[1]; } else { retval = "error: unable to create table -- " + errmsg; } } } return retval; } static string com_delete_logline_table(string cmdline, vector &args) { string retval = "error: expecting a table name"; if (args.size() == 0) { args.push_back("custom-table"); } else if (args.size() == 2) { string rc = lnav_data.ld_vtab_manager->unregister_vtab(args[1]); if (rc.empty()) { if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->rem_possibility(LNM_COMMAND, "custom-table", args[1]); } retval = "info: deleted logline table"; } else { retval = "error: " + rc; } } return retval; } static string com_session(string cmdline, vector &args) { string retval = "error: expecting a command to save to the session file"; if (args.size() == 0) {} else if (args.size() >= 2) { /* XXX put these in a map */ if (args[1] != "highlight" && args[1] != "enable-word-wrap" && args[1] != "disable-word-wrap" && args[1] != "filter-in" && args[1] != "filter-out" && args[1] != "enable-filter" && args[1] != "disable-filter") { retval = "error: only the highlight, filter, and word-wrap commands are " "supported"; } else if (getenv("HOME") == NULL) { retval = "error: the HOME environment variable is not set"; } else { string old_file_name, new_file_name; string::size_type space; string saved_cmd; space = cmdline.find(' '); while (isspace(cmdline[space])) { space += 1; } saved_cmd = cmdline.substr(space); old_file_name = dotlnav_path("session"); new_file_name = dotlnav_path("session.tmp"); ifstream session_file(old_file_name.c_str()); ofstream new_session_file(new_file_name.c_str()); if (!new_session_file) { retval = "error: cannot write to session file"; } else { bool added = false; string line; if (session_file.is_open()) { while (getline(session_file, line)) { if (line == saved_cmd) { added = true; break; } new_session_file << line << endl; } } if (!added) { new_session_file << saved_cmd << endl; rename(new_file_name.c_str(), old_file_name.c_str()); } else { remove(new_file_name.c_str()); } retval = "info: session file saved"; } } } return retval; } static string com_open(string cmdline, vector &args) { string retval = "error: expecting file name to open"; if (args.size() == 0) { args.push_back("filename"); return ""; } else if (args.size() < 2) { return retval; } static_root_mem wordmem; list::iterator file_iter; size_t colon_index; int top = 0; string pat; pat = trim(cmdline.substr(cmdline.find(args[1], args[0].size()))); int rc = wordexp(pat.c_str(), wordmem.inout(), WRDE_NOCMD | WRDE_UNDEF); if (!wordexperr(rc, retval)) { return retval; } for (int lpc = 0; lpc < wordmem->we_wordc; lpc++) { string fn = wordmem->we_wordv[lpc]; if (access(fn.c_str(), R_OK) != 0 && (colon_index = fn.rfind(':')) != string::npos) { if (sscanf(&fn.c_str()[colon_index + 1], "%d", &top) == 1) { fn = fn.substr(0, colon_index); } } for (file_iter = lnav_data.ld_files.begin(); file_iter != lnav_data.ld_files.end(); ++file_iter) { logfile *lf = *file_iter; if (lf->get_filename() == fn) { if (lf->get_format() != NULL) { retval = "info: log file already loaded"; break; } else { lnav_data.ld_files_to_front.push_back(make_pair(fn, top)); retval = ""; break; } } } if (file_iter == lnav_data.ld_files.end()) { auto_mem abspath; struct stat st; if (is_glob(fn.c_str())) { lnav_data.ld_file_names.insert(make_pair(fn, -1)); retval = "info: watching -- " + fn; } else if (stat(fn.c_str(), &st) == -1) { retval = ("error: cannot stat file: " + fn + " -- " + strerror(errno)); } else if ((abspath = realpath(fn.c_str(), NULL)) == NULL) { retval = "error: cannot find file"; } else if (S_ISDIR(st.st_mode)) { string dir_wild(abspath.in()); if (dir_wild[dir_wild.size() - 1] == '/') { dir_wild.resize(dir_wild.size() - 1); } lnav_data.ld_file_names.insert(make_pair(dir_wild + "/*", -1)); retval = "info: watching -- " + dir_wild; } else if (!S_ISREG(st.st_mode)) { retval = "error: not a regular file or directory"; } else if (access(fn.c_str(), R_OK) == -1) { retval = (string("error: cannot read file -- ") + strerror(errno)); } else { fn = abspath.in(); lnav_data.ld_file_names.insert(make_pair(fn, -1)); retval = "info: opened -- " + fn; lnav_data.ld_files_to_front.push_back(make_pair(fn, top)); if (lnav_data.ld_rl_view != NULL) { lnav_data.ld_rl_view->set_alt_value(HELP_MSG_1( X, "to close the file")); } } } } return retval; } static string com_close(string cmdline, vector &args) { string retval = "error: close must be run in the log or text file views"; if (args.empty()) { } else { textview_curses *tc = lnav_data.ld_view_stack.top(); string fn; if (tc == &lnav_data.ld_views[LNV_TEXT]) { textfile_sub_source &tss = lnav_data.ld_text_source; if (tss.tss_files.empty()) { retval = "error: no text files are opened"; } else { fn = tss.current_file()->get_filename(); tss.current_file()->close(); if (tss.tss_files.size() == 1) { lnav_data.ld_view_stack.pop(); } } } else if (tc == &lnav_data.ld_views[LNV_LOG]) { if (tc->get_inner_height() == 0) { retval = "error: no log files loaded"; } else { logfile_sub_source &lss = lnav_data.ld_log_source; vis_line_t vl = tc->get_top(); content_line_t cl = lss.at(vl); logfile *lf = lss.find(cl); fn = lf->get_filename(); lf->close(); } } if (!fn.empty()) { lnav_data.ld_file_names.erase(make_pair(fn, -1)); retval = "info: closed -- " + fn; } } return retval; } static string com_partition_name(string cmdline, vector &args) { string retval = "error: expecting partition name"; if (args.size() == 0) { return ""; } else if (args.size() > 1) { textview_curses &tc = lnav_data.ld_views[LNV_LOG]; logfile_sub_source &lss = lnav_data.ld_log_source; std::map &bm = lss.get_user_bookmark_metadata(); args[1] = trim(cmdline.substr(cmdline.find(args[1], args[0].size()))); tc.set_user_mark(&textview_curses::BM_PARTITION, tc.get_top(), true); bookmark_metadata &line_meta = bm[lss.at(tc.get_top())]; line_meta.bm_name = args[1]; retval = "info: name set for partition"; } return retval; } static string com_clear_partition(string cmdline, vector &args) { string retval = ""; if (args.size() == 0) { return ""; } else if (args.size() == 1) { textview_curses &tc = lnav_data.ld_views[LNV_LOG]; logfile_sub_source &lss = lnav_data.ld_log_source; bookmark_vector &bv = tc.get_bookmarks()[ &textview_curses::BM_PARTITION]; std::map &bm = lss.get_user_bookmark_metadata(); vis_line_t part_start; if (binary_search(bv.begin(), bv.end(), tc.get_top())) { part_start = tc.get_top(); } else { part_start = bv.prev(tc.get_top()); } if (part_start == -1) { retval = "error: top line is not in a partition"; } else { tc.set_user_mark( &textview_curses::BM_PARTITION, part_start, false); bm.erase(lss.at(part_start)); retval = "info: cleared partition name"; } } return retval; } static string com_summarize(string cmdline, vector &args) { static pcrecpp::RE db_column_converter("\""); string retval = ""; if (args.size() == 0) { args.push_back("colname"); return retval; } else if (!setup_logline_table()) { retval = "error: no log data available"; } else if (args.size() == 1) { retval = "error: no columns specified"; } else { auto_mem query_frag; std::vector other_columns; std::vector num_columns; auto_mem stmt(sqlite3_finalize); int retcode; string query; query = "SELECT "; for (size_t lpc = 1; lpc < args.size(); lpc++) { if (lpc > 1) query += ", "; query += args[lpc]; } query += " FROM logline "; retcode = sqlite3_prepare_v2(lnav_data.ld_db.in(), query.c_str(), -1, stmt.out(), NULL); if (retcode != SQLITE_OK) { const char *errmsg = sqlite3_errmsg(lnav_data.ld_db); return "error: " + string(errmsg); } switch (sqlite3_step(stmt.in())) { case SQLITE_OK: case SQLITE_DONE: { return "error: no data"; } break; case SQLITE_ROW: break; default: { const char *errmsg; errmsg = sqlite3_errmsg(lnav_data.ld_db); return "error: " + string(errmsg); } break; } for (int lpc = 0; lpc < sqlite3_column_count(stmt.in()); lpc++) { switch (sqlite3_column_type(stmt.in(), lpc)) { case SQLITE_INTEGER: case SQLITE_FLOAT: num_columns.push_back(args[lpc + 1]); break; default: other_columns.push_back(args[lpc + 1]); break; } } query = "SELECT"; for (std::vector::iterator iter = other_columns.begin(); iter != other_columns.end(); ++iter) { if (iter != other_columns.begin()) { query += ","; } query_frag = sqlite3_mprintf(" %s as \"c_%s\", count(*) as \"count_%s\"", iter->c_str(), iter->c_str(), iter->c_str()); query += query_frag; } if (!other_columns.empty() && !num_columns.empty()) { query += ", "; } for (std::vector::iterator iter = num_columns.begin(); iter != num_columns.end(); ++iter) { if (iter != num_columns.begin()) { query += ","; } query_frag = sqlite3_mprintf(" sum(\"%s\"), " " min(\"%s\"), " " avg(\"%s\"), " " median(\"%s\"), " " stddev(\"%s\"), " " max(\"%s\") ", iter->c_str(), iter->c_str(), iter->c_str(), iter->c_str(), iter->c_str(), iter->c_str()); query += query_frag; } query += " FROM logline WHERE startswith(logline.log_part, '.') = 0 "; for (std::vector::iterator iter = other_columns.begin(); iter != other_columns.end(); ++iter) { if (iter == other_columns.begin()) { query += " GROUP BY "; } else{ query += ","; } query_frag = sqlite3_mprintf(" \"c_%s\"", iter->c_str()); query += query_frag; } for (std::vector::iterator iter = other_columns.begin(); iter != other_columns.end(); ++iter) { if (iter == other_columns.begin()) { query += " ORDER BY "; } else{ query += ","; } query_frag = sqlite3_mprintf(" \"count_%s\" desc, \"c_%s\" collate naturalnocase asc", iter->c_str(), iter->c_str()); query += query_frag; } db_label_source & dls = lnav_data.ld_db_rows; hist_source & hs = lnav_data.ld_db_source; hs.clear(); dls.clear(); retcode = sqlite3_prepare_v2(lnav_data.ld_db.in(), query.c_str(), -1, stmt.out(), NULL); if (retcode != SQLITE_OK) { const char *errmsg = sqlite3_errmsg(lnav_data.ld_db); retval = "error: " + string(errmsg); } else if (stmt == NULL) { retval = ""; } else { bool done = false; while (!done) { retcode = sqlite3_step(stmt.in()); switch (retcode) { case SQLITE_OK: case SQLITE_DONE: done = true; break; case SQLITE_ROW: sql_callback(stmt.in()); break; default: { const char *errmsg; errmsg = sqlite3_errmsg(lnav_data.ld_db); retval = "error: " + string(errmsg); done = true; } break; } } if (retcode == SQLITE_DONE) { lnav_data.ld_views[LNV_LOG].reload_data(); lnav_data.ld_views[LNV_DB].reload_data(); lnav_data.ld_views[LNV_DB].set_left(0); if (dls.dls_rows.size() > 0) { ensure_view(&lnav_data.ld_views[LNV_DB]); } } lnav_data.ld_bottom_source.update_loading(0, 0); lnav_data.ld_status[LNS_BOTTOM].do_update(); } } return retval; } static string com_add_test(string cmdline, vector &args) { string retval = ""; if (args.size() == 0) {} else if (args.size() > 1) { retval = "error: not expecting any arguments"; } else { textview_curses *tc = lnav_data.ld_view_stack.top(); bookmark_vector &bv = tc->get_bookmarks()[&textview_curses::BM_USER]; bookmark_vector::iterator iter; for (iter = bv.begin(); iter != bv.end(); ++iter) { auto_mem file(fclose); char path[PATH_MAX]; string line; tc->grep_value_for_line(*iter, line); line.insert(0, 13, ' '); snprintf(path, sizeof(path), "%s/test/log-samples/sample-%s.txt", getenv("LNAV_SRC"), hash_string(line).c_str()); if ((file = fopen(path, "w")) == NULL) { perror("fopen failed"); } else { fprintf(file, "%s\n", line.c_str()); } } } return retval; } static string com_switch_to_view(string cmdline, vector &args) { string retval = ""; if (args.size() == 0) { args.push_back("viewname"); } else if (args.size() > 1) { bool found = false; for (int lpc = 0; lnav_view_strings[lpc] && !found; lpc++) { if (strcasecmp(args[1].c_str(), lnav_view_strings[lpc]) == 0) { ensure_view(&lnav_data.ld_views[lpc]); found = true; } } if (!found) { retval = "error: invalid view name -- " + args[1]; } } return retval; } static string com_load_session(string cmdline, vector &args) { if (args.empty()) { } else { scan_sessions(); load_session(); lnav_data.ld_views[LNV_LOG].reload_data(); } return ""; } static string com_save_session(string cmdline, vector &args) { if (args.empty()) { } else { save_session(); } return ""; } static string com_set_min_log_level(string cmdline, vector &args) { string retval = "error: expecting log level name"; if (args.empty()) { args.push_back("levelname"); } else if (args.size() == 2) { logline::level_t new_level; new_level = logline::string2level( args[1].c_str(), args[1].size(), true); if (lnav_data.ld_level_filter.lf_min_level != new_level) { lnav_data.ld_level_filter.lf_min_level = new_level; lnav_data.ld_log_source.filter_changed(); rebuild_indexes(true); } retval = ("info: minimum log level is now -- " + string(logline::level_names[new_level])); } return retval; } void init_lnav_commands(readline_context::command_map_t &cmd_map) { cmd_map["adjust-log-time"] = com_adjust_log_time; cmd_map["unix-time"] = com_unix_time; cmd_map["current-time"] = com_current_time; cmd_map["goto"] = com_goto; cmd_map["graph"] = com_graph; cmd_map["help"] = com_help; cmd_map["highlight"] = com_highlight; cmd_map["filter-in"] = com_filter; cmd_map["filter-out"] = com_filter; cmd_map["append-to"] = com_save_to; cmd_map["write-to"] = com_save_to; cmd_map["write-csv-to"] = com_save_to; cmd_map["write-json-to"] = com_save_to; cmd_map["enable-filter"] = com_enable_filter; cmd_map["disable-filter"] = com_disable_filter; cmd_map["enable-word-wrap"] = com_enable_word_wrap; cmd_map["disable-word-wrap"] = com_disable_word_wrap; cmd_map["create-logline-table"] = com_create_logline_table; cmd_map["delete-logline-table"] = com_delete_logline_table; cmd_map["open"] = com_open; cmd_map["close"] = com_close; cmd_map["partition-name"] = com_partition_name; cmd_map["clear-partition"] = com_clear_partition; cmd_map["session"] = com_session; cmd_map["summarize"] = com_summarize; cmd_map["switch-to-view"] = com_switch_to_view; cmd_map["load-session"] = com_load_session; cmd_map["save-session"] = com_save_session; cmd_map["set-min-log-level"] = com_set_min_log_level; if (getenv("LNAV_SRC") != NULL) { cmd_map["add-test"] = com_add_test; } } lnav-0.7.0/src/lnav_commands.hh000664 000765 000024 00000003411 12211635053 016656 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file lnav_commands.hh */ #ifndef __lnav_commands_hh #define __lnav_commands_hh #include "readline_curses.hh" /** * Initialize the given map with the builtin lnav commands. */ void init_lnav_commands(readline_context::command_map_t &cmd_map); #endif lnav-0.7.0/src/lnav_config.cc000664 000765 000024 00000006225 12306073545 016325 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file lnav_config.cc */ #include "config.h" #include #include #include #include #include #include "lnav_log.hh" #include "auto_mem.hh" #include "lnav_config.hh" using namespace std; static const int MAX_CRASH_LOG_COUNT = 16; string dotlnav_path(const char *sub) { string retval; char * home; home = getenv("HOME"); if (home) { char hpath[2048]; snprintf(hpath, sizeof(hpath), "%s/.lnav/%s", home, sub); retval = hpath; } else { retval = sub; } return retval; } bool check_experimental(const char *feature_name) { const char *env_value = getenv("LNAV_EXP"); require(feature_name != NULL); if (env_value && strcasestr(env_value, feature_name)) { return true; } return false; } void ensure_dotlnav(void) { string path = dotlnav_path(""); if (!path.empty()) { mkdir(path.c_str(), 0755); } path = dotlnav_path("formats"); if (!path.empty()) { mkdir(path.c_str(), 0755); } path = dotlnav_path("crash"); if (!path.empty()) { mkdir(path.c_str(), 0755); } lnav_log_crash_dir = strdup(path.c_str()); { static_root_mem gl; path += "/*"; if (glob(path.c_str(), GLOB_NOCHECK, NULL, gl.inout()) == 0) { for (int lpc = 0; lpc < ((int)gl->gl_pathc - MAX_CRASH_LOG_COUNT); lpc++) { remove(gl->gl_pathv[lpc]); } } } path = dotlnav_path("formats/default"); if (!path.empty()) { mkdir(path.c_str(), 0755); } } lnav-0.7.0/src/lnav_config.hh000664 000765 000024 00000004355 12211635054 016333 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file lnav_config.hh */ #ifndef _lnav_config_hh #define _lnav_config_hh #include /** * Compute the path to a file in the user's '.lnav' directory. * * @param sub The path to the file in the '.lnav' directory. * @return The full path */ std::string dotlnav_path(const char *sub); /** * Check if an experimental feature should be enabled by * examining the LNAV_EXP environment variable. * * @param feature_name The feature name to check for in * the LNAV_EXP environment variable. * * @return True if the feature was mentioned in the env * var and should be enabled. */ bool check_experimental(const char *feature_name); /** * Ensure that the '.lnav' directory exists. */ void ensure_dotlnav(void); #endif lnav-0.7.0/src/lnav_log.cc000664 000765 000024 00000021060 12315674736 015644 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file lnav_log.cc */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_EXECINFO_H #include #endif #include #include #include #include #if defined HAVE_NCURSESW_CURSES_H # include #elif defined HAVE_NCURSESW_H # include #elif defined HAVE_NCURSES_CURSES_H # include #elif defined HAVE_NCURSES_H # include #elif defined HAVE_CURSES_H # include #else # error "SysV or X/Open-compatible Curses header file required" #endif #include "lnav_log.hh" static const size_t BUFFER_SIZE = 256 * 1024; static const size_t MAX_LOG_LINE_SIZE = 2048; static const char *CRASH_MSG = "\n" "\n" "==== GURU MEDITATION ====\n" "Unfortunately, lnav has crashed, sorry for the inconvenience.\n" "\n" "You can help improve lnav by sending the following file to " PACKAGE_BUGREPORT " :\n" " %s\n" "=========================\n"; FILE *lnav_log_file; lnav_log_level_t lnav_log_level; const char *lnav_log_crash_dir; const struct termios *lnav_log_orig_termios; static struct { size_t lr_length; off_t lr_frag_start; off_t lr_frag_end; char lr_data[BUFFER_SIZE]; } log_ring = { 0, BUFFER_SIZE, 0, }; static const char *LEVEL_NAMES[] = { "D", "I", "W", "E", }; static char *log_alloc(void) { off_t data_end = log_ring.lr_length + MAX_LOG_LINE_SIZE; if (data_end >= BUFFER_SIZE) { const char *new_start = &log_ring.lr_data[MAX_LOG_LINE_SIZE]; new_start = (const char *)memchr( new_start, '\n', log_ring.lr_length - MAX_LOG_LINE_SIZE); log_ring.lr_frag_start = new_start - log_ring.lr_data; log_ring.lr_frag_end = log_ring.lr_length; log_ring.lr_length = 0; assert(log_ring.lr_frag_start >= 0); assert(log_ring.lr_frag_start <= BUFFER_SIZE); } else if (data_end >= log_ring.lr_frag_start) { const char *new_start = &log_ring.lr_data[log_ring.lr_frag_start]; new_start = (const char *)memchr( new_start, '\n', log_ring.lr_frag_end - log_ring.lr_frag_start); assert(new_start != NULL); log_ring.lr_frag_start = new_start - log_ring.lr_data; assert(log_ring.lr_frag_start >= 0); assert(log_ring.lr_frag_start <= BUFFER_SIZE); } return &log_ring.lr_data[log_ring.lr_length]; } void log_host_info(void) { struct utsname un; uname(&un); log_info("uname:") log_info(" sysname=%s", un.sysname); log_info(" nodename=%s", un.nodename); log_info(" machine=%s", un.machine); log_info(" release=%s", un.release); log_info(" version=%s", un.version); log_info("Environment:"); log_info(" TERM=%s", getenv("TERM")); } void log_msg(lnav_log_level_t level, const char *src_file, int line_number, const char *fmt, ...) { struct timeval curr_time; struct tm localtm; size_t prefix_size; va_list args; char *line; int rc; if (level < lnav_log_level) { return; } va_start(args, fmt); gettimeofday(&curr_time, NULL); localtime_r(&curr_time.tv_sec, &localtm); line = log_alloc(); prefix_size = snprintf( line, MAX_LOG_LINE_SIZE, "%4d-%02d-%02dT%02d:%02d:%02d.%03d %s %s:%d ", localtm.tm_year + 1900, localtm.tm_mon + 1, localtm.tm_mday, localtm.tm_hour, localtm.tm_min, localtm.tm_sec, curr_time.tv_usec / 1000, LEVEL_NAMES[level], basename((char *)src_file), line_number); rc = vsnprintf(&line[prefix_size], MAX_LOG_LINE_SIZE - prefix_size, fmt, args); if (rc >= (MAX_LOG_LINE_SIZE - prefix_size)) { rc = MAX_LOG_LINE_SIZE - prefix_size - 1; } line[prefix_size + rc] = '\n'; log_ring.lr_length += prefix_size + rc + 1; if (lnav_log_file != NULL) { fwrite(line, 1, prefix_size + rc + 1, lnav_log_file); fflush(lnav_log_file); } va_end(args); } static void sigabrt(int sig) { char crash_path[1024], latest_crash_path[1024]; int fd, frame_count; void *frames[128]; struct tm localtm; time_t curr_time; if (lnav_log_crash_dir == NULL) { return; } log_error("Received signal: %d", sig); #ifdef HAVE_EXECINFO_H frame_count = backtrace(frames, 128); #endif curr_time = time(NULL); localtime_r(&curr_time, &localtm); snprintf(crash_path, sizeof(crash_path), "%s/crash-%4d-%02d-%02d-%02d-%02d-%02d.%d.log", lnav_log_crash_dir, localtm.tm_year + 1900, localtm.tm_mon + 1, localtm.tm_mday, localtm.tm_hour, localtm.tm_min, localtm.tm_sec, getpid()); snprintf(latest_crash_path, sizeof(latest_crash_path), "%s/latest-crash.log", lnav_log_crash_dir); if ((fd = open(crash_path, O_CREAT|O_TRUNC|O_WRONLY, 0600)) != -1) { if (log_ring.lr_frag_start < BUFFER_SIZE) { write(fd, &log_ring.lr_data[log_ring.lr_frag_start], log_ring.lr_frag_end - log_ring.lr_frag_start); } write(fd, log_ring.lr_data, log_ring.lr_length); #ifdef HAVE_EXECINFO_H backtrace_symbols_fd(frames, frame_count, fd); #endif close(fd); remove(latest_crash_path); symlink(crash_path, latest_crash_path); } if (lnav_log_orig_termios != NULL) { tcsetattr(STDOUT_FILENO, TCSAFLUSH, lnav_log_orig_termios); } fprintf(stderr, CRASH_MSG, crash_path); #ifdef ATTACH_ON_SIGNAL if (isatty(STDIN_FILENO)) { char response; fprintf(stderr, "\nWould you like to attach a debugger? (y/N) "); fflush(stderr); scanf("%c", &response); if (tolower(response) == 'y') { pid_t lnav_pid = getpid(); pid_t child_pid; switch ((child_pid = fork())) { case 0: { char pid_str[32]; snprintf(pid_str, sizeof(pid_str), "--pid=%d", lnav_pid); execlp("gdb", "gdb", pid_str, NULL); snprintf(pid_str, sizeof(pid_str), "--attach-pid=%d", lnav_pid); execlp("lldb", "lldb", pid_str, NULL); fprintf(stderr, "Could not attach gdb or lldb, exiting.\n"); _exit(1); break; } case -1: { break; } default: { int status; while (wait(&status) < 0) { } break; } } } } #endif _exit(1); } void log_install_handlers(void) { signal(SIGABRT, sigabrt); signal(SIGSEGV, sigabrt); signal(SIGBUS, sigabrt); signal(SIGILL, sigabrt); signal(SIGFPE, sigabrt); } void log_abort(void) { sigabrt(SIGABRT); _exit(1); } lnav-0.7.0/src/lnav_log.hh000664 000765 000024 00000006074 12306076737 015663 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file lnav_log.hh */ #ifndef __lnav_log_hh #define __lnav_log_hh #include #include #include #include #ifndef __dead2 #define __dead2 __attribute__((noreturn)) #endif enum lnav_log_level_t { LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_ERROR, }; void log_host_info(void); void log_msg(enum lnav_log_level_t level, const char *src_file, int line_number, const char *fmt, ...); void log_install_handlers(void); void log_abort(void) __dead2; extern FILE *lnav_log_file; extern const char *lnav_log_crash_dir; extern const struct termios *lnav_log_orig_termios; extern enum lnav_log_level_t lnav_log_level; #define log_msg_wrapper(level, fmt...) \ do { \ if (lnav_log_level <= level) { \ log_msg(level, __FILE__, __LINE__, fmt); \ } \ } \ while (false) #define log_error(fmt...) \ log_msg_wrapper(LOG_LEVEL_ERROR, fmt); #define log_warning(fmt...) \ log_msg_wrapper(LOG_LEVEL_WARNING, fmt); #define log_info(fmt...) \ log_msg_wrapper(LOG_LEVEL_INFO, fmt); #define log_debug(fmt...) \ log_msg_wrapper(LOG_LEVEL_DEBUG, fmt); #define require(e) \ ((void) ((e) ? 0 : __require (#e, __FILE__, __LINE__))) #define __require(e, file, line) \ (log_msg(LOG_LEVEL_ERROR, file, line, "failed precondition `%s'", e), log_abort(), 1) #define ensure(e) \ ((void) ((e) ? 0 : __ensure (#e, __FILE__, __LINE__))) #define __ensure(e, file, line) \ (log_msg(LOG_LEVEL_ERROR, file, line, "failed postcondition `%s'", e), log_abort(), 1) #endif lnav-0.7.0/src/lnav_util.cc000664 000765 000024 00000026071 12313316432 016027 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file lnav_util.cc * * Dumping ground for useful functions with no other home. */ #include "config.h" #include #include #include #include #include "auto_fd.hh" #include "ptimec.hh" #include "lnav_util.hh" std::string hash_string(const std::string &str) { byte_array<2, uint64> hash; SpookyHash context; context.Init(0, 0); context.Update(str.c_str(), str.length()); context.Final(hash.out(0), hash.out(1)); return hash.to_string(); } std::string time_ago(time_t last_time) { time_t delta, current_time = time(NULL); const char *fmt; char buffer[64]; int amount; delta = current_time - last_time; if (delta < 0) { return "in the future"; } else if (delta < 60) { return "just now"; } else if (delta < (60 * 2)) { return "one minute ago"; } else if (delta < (60 * 60)) { fmt = "%d minutes ago"; amount = delta / 60; } else if (delta < (2 * 60 * 60)) { return "one hour ago"; } else if (delta < (24 * 60 * 60)) { fmt = "%d hours ago"; amount = delta / (60 * 60); } else if (delta < (2 * 24 * 60 * 60)) { return "one day ago"; } else if (delta < (365 * 24 * 60 * 60)) { fmt = "%d days ago"; amount = delta / (24 * 60 * 60); } else { return "over a year ago"; } snprintf(buffer, sizeof(buffer), fmt, amount); return std::string(buffer); } /* XXX figure out how to do this with the template */ void sqlite_close_wrapper(void *mem) { sqlite3_close((sqlite3 *)mem); } std::string get_current_dir(void) { char cwd[FILENAME_MAX]; std::string retval = "."; if (getcwd(cwd, sizeof(cwd)) == NULL) { perror("getcwd"); } else { retval = std::string(cwd); } if (retval != "/") { retval += "/"; } return retval; } bool change_to_parent_dir(void) { bool retval = false; char cwd[3] = ""; if (getcwd(cwd, sizeof(cwd)) == NULL) { /* perror("getcwd"); */ } if (strcmp(cwd, "/") != 0) { if (chdir("..") == -1) { perror("chdir('..')"); } else { retval = true; } } return retval; } file_format_t detect_file_format(const std::string &filename) { file_format_t retval = FF_UNKNOWN; auto_fd fd; if ((fd = open(filename.c_str(), O_RDONLY)) != -1) { char buffer[32]; int rc; if ((rc = read(fd, buffer, sizeof(buffer))) > 0) { if (rc > 16 && strncmp(buffer, "SQLite format 3", 16) == 0) { retval = FF_SQLITE_DB; } } } return retval; } static time_t BAD_DATE = -1; time_t tm2sec(const struct tm *t) { int year; time_t days; const int dayoffset[12] = { 306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275 }; year = t->tm_year; if (year < 70 || ((sizeof(time_t) <= 4) && (year >= 138))) { return BAD_DATE; } /* shift new year to 1st March in order to make leap year calc easy */ if (t->tm_mon < 2) { year--; } /* Find number of days since 1st March 1900 (in the Gregorian calendar). */ days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4; days += dayoffset[t->tm_mon] + t->tm_mday - 1; days -= 25508; /* 1 jan 1970 is 25508 days since 1 mar 1900 */ days = ((days * 24 + t->tm_hour) * 60 + t->tm_min) * 60 + t->tm_sec; if (days < 0) { return BAD_DATE; } /* must have overflowed */ else { #ifdef HAVE_STRUCT_TM_TM_ZONE if (t->tm_zone) { days -= t->tm_gmtoff; } #endif return days; } /* must be a valid time */ } bool next_format(const char *fmt[], int &index, int &locked_index) { bool retval = true; if (locked_index == -1) { index += 1; if (fmt[index] == NULL) { retval = false; } } else if (index == locked_index) { retval = false; } else { index = locked_index; } return retval; } static const char *time_fmt_with_zone = "%a %b %d %H:%M:%S "; const char *std_time_fmt[] = { "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M:%SZ", "%Y/%m/%d %H:%M:%S", "%Y/%m/%d %H:%M", "%a %b %d %H:%M:%S %Y", "%a %b %d %H:%M:%S %Z %Y", time_fmt_with_zone, "%d/%b/%Y:%H:%M:%S +0000", "%d/%b/%Y:%H:%M:%S %z", "%b %d %H:%M:%S", "%m/%d/%y %H:%M:%S", "%m%d %H:%M:%S", "+%s", NULL, }; const char *date_time_scanner::scan(const char *time_dest, const char *time_fmt[], struct tm *tm_out, struct timeval &tv_out) { int curr_time_fmt = -1; bool found = false; const char *retval = NULL; if (!time_fmt) { time_fmt = PTIMEC_FORMAT_STR; } while (next_format(time_fmt, curr_time_fmt, this->dts_fmt_lock)) { *tm_out = this->dts_base_tm; if (time_dest[0] == '+') { int gmt_int, off; retval = NULL; if (sscanf(time_dest, "+%d%n", &gmt_int, &off) == 1) { time_t gmt = gmt_int; if (this->dts_local_time) { localtime_r(&gmt, tm_out); #ifdef HAVE_STRUCT_TM_TM_ZONE tm_out->tm_zone = NULL; #endif tm_out->tm_isdst = 0; gmt = tm2sec(tm_out); } tv_out.tv_sec = gmt; tv_out.tv_usec = 0; this->dts_fmt_lock = curr_time_fmt; this->dts_fmt_len = off; retval = time_dest + off; found = true; break; } } else if (time_fmt == PTIMEC_FORMAT_STR) { ptime_func func = PTIMEC_FORMATS[curr_time_fmt].pf_func; off_t off = 0; #ifdef HAVE_STRUCT_TM_TM_ZONE tm_out->tm_zone = NULL; #endif if (func(tm_out, time_dest, off, strlen(time_dest))) { retval = &time_dest[off]; if (tm_out->tm_year < 70) { tm_out->tm_year = 80; } if (this->dts_local_time) { time_t gmt = tm2sec(tm_out); localtime_r(&gmt, tm_out); #ifdef HAVE_STRUCT_TM_TM_ZONE tm_out->tm_zone = NULL; #endif tm_out->tm_isdst = 0; } tv_out.tv_sec = tm2sec(tm_out); tv_out.tv_usec = 0; this->dts_fmt_lock = curr_time_fmt; this->dts_fmt_len = retval - time_dest; found = true; break; } } else if ((retval = strptime(time_dest, time_fmt[curr_time_fmt], tm_out)) != NULL) { if (time_fmt[curr_time_fmt] == time_fmt_with_zone) { int lpc; for (lpc = 0; retval[lpc] && retval[lpc] != ' '; lpc++) { } if (retval[lpc] == ' ' && sscanf(&retval[lpc], "%d", &tm_out->tm_year) == 1) { lpc += 1; for (; retval[lpc] && isdigit(retval[lpc]); lpc++) { } retval = &retval[lpc]; } } if (tm_out->tm_year < 70) { tm_out->tm_year = 80; } if (this->dts_local_time) { time_t gmt = tm2sec(tm_out); localtime_r(&gmt, tm_out); #ifdef HAVE_STRUCT_TM_TM_ZONE tm_out->tm_zone = NULL; #endif tm_out->tm_isdst = 0; } tv_out.tv_sec = tm2sec(tm_out); tv_out.tv_usec = 0; this->dts_fmt_lock = curr_time_fmt; this->dts_fmt_len = retval - time_dest; found = true; break; } } if (!found) { retval = NULL; } if (retval != NULL) { /* Try to pull out the milli/micro-second value. */ if (retval[0] == '.' || retval[0] == ',') { int sub_seconds = 0, sub_len = 0; if (sscanf(retval + 1, "%d%n", &sub_seconds, &sub_len) == 1) { switch (sub_len) { case 3: tv_out.tv_usec = sub_seconds * 1000; this->dts_fmt_len += 1 + sub_len; break; case 6: tv_out.tv_usec = sub_seconds; this->dts_fmt_len += 1 + sub_len; break; } } } } return retval; } template size_t strtonum(T &num_out, const char *string, size_t len) { size_t retval = 0; T sign = 1; num_out = 0; for (; retval < len && isspace(string[retval]); retval++); for (; retval < len && string[retval] == '-'; retval++) { sign *= -1; } for (; retval < len && string[retval] == '+'; retval++); for (; retval < len && isdigit(string[retval]); retval++) { num_out *= 10; num_out += string[retval] - '0'; } return retval; } template size_t strtonum(long long &num_out, const char *string, size_t len); template size_t strtonum(long &num_out, const char *string, size_t len); template size_t strtonum(int &num_out, const char *string, size_t len); lnav-0.7.0/src/lnav_util.hh000664 000765 000024 00000012353 12303527475 016051 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file lnav_util.hh * * Dumping ground for useful functions with no other home. */ #ifndef __lnav_util_hh #define __lnav_util_hh #include #include #include "spookyhash/SpookyV2.h" #include #include "byte_array.hh" inline std::string trim(const std::string &str) { std::string::size_type start, end; for (start = 0; start < str.size() && isspace(str[start]); start++); for (end = str.size(); end > 0 && isspace(str[end - 1]); end--); return str.substr(start, end - start); } #undef rounddown /** * Round down a number based on a given granularity. * * @param * @param step The granularity. */ inline int rounddown(size_t size, int step) { return size - (size % step); } inline int rounddown_offset(size_t size, int step, int offset) { return size - ((size - offset) % step); } inline int roundup_size(size_t size, int step) { int retval = size + step; retval -= (retval % step); return retval; } inline time_t day_num(time_t ti) { return ti / (24 * 60 * 60); } inline time_t hour_num(time_t ti) { return ti / (60 * 60); } std::string time_ago(time_t last_time); #if SIZEOF_OFF_T == 8 #define FORMAT_OFF_T "%qd" #elif SIZEOF_OFF_T == 4 #define FORMAT_OFF_T "%ld" #else #error "off_t has unhandled size..." #endif struct hash_updater { hash_updater(SpookyHash *context) : su_context(context) { }; void operator()(const std::string &str) { this->su_context->Update(str.c_str(), str.length()); } SpookyHash *su_context; }; std::string hash_string(const std::string &str); template struct object_field_t { object_field_t(UnaryFunction &func, Member &mem) : of_func(func), of_mem(mem) {}; template void operator()(Object obj) { this->of_func(obj.*(this->of_mem)); }; UnaryFunction &of_func; Member of_mem; }; template object_field_t object_field(UnaryFunction &func, Member mem) { return object_field_t(func, mem); } /* XXX figure out how to do this with the template */ void sqlite_close_wrapper(void *mem); std::string get_current_dir(void); bool change_to_parent_dir(void); enum file_format_t { FF_UNKNOWN, FF_SQLITE_DB, }; file_format_t detect_file_format(const std::string &filename); bool next_format(const char *fmt[], int &index, int &locked_index); inline bool is_glob(const char *fn) { return (strchr(fn, '*') != NULL || strchr(fn, '?') != NULL || strchr(fn, '[') != NULL); }; /** * Convert the time stored in a 'tm' struct into epoch time. * * @param t The 'tm' structure to convert to epoch time. * @return The given time in seconds since the epoch. */ time_t tm2sec(const struct tm *t); extern const char *std_time_fmt[]; struct date_time_scanner { date_time_scanner() : dts_local_time(false) { this->clear(); }; void clear(void) { this->dts_base_time = 0; memset(&this->dts_base_tm, 0, sizeof(this->dts_base_tm)); this->dts_fmt_lock = -1; this->dts_fmt_len = -1; }; void set_base_time(time_t base_time) { this->dts_base_time = base_time; localtime_r(&base_time, &this->dts_base_tm); }; bool dts_local_time; time_t dts_base_time; struct tm dts_base_tm; int dts_fmt_lock; int dts_fmt_len; const char *scan(const char *time_src, const char *time_fmt[], struct tm *tm_out, struct timeval &tv_out); }; template size_t strtonum(T &num_out, const char *data, size_t len); #endif lnav-0.7.0/src/log_accel.cc000644 000765 000024 00000003234 12311417453 015737 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file log_accel.cc */ #include "config.h" #include "log_accel.hh" const double log_accel::MIN_RANGE = 5.0; const double log_accel::THRESHOLD = 0.1; lnav-0.7.0/src/log_accel.hh000644 000765 000024 00000012622 12311421676 015754 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file log_accel.hh */ #ifndef __log_accel_h #define __log_accel_h #include #include #include #include "lnav_log.hh" /** * Helper class for figuring out changes in the log message rate. */ class log_accel { public: /*< The direction of the message rate: steady, accelerating, or decelerating */ enum direction_t { A_STEADY, A_DECEL, A_ACCEL, }; log_accel() : la_last_point_set(false), la_min_velocity(INT64_MAX), la_max_velocity(INT64_MIN), la_velocity_size(0) { }; /** * Add a time point that will be used to compute velocity and then * acceleration. Points should be added in reverse order, from most * recent to oldest. * * @param point The point in time. * @return True if more points can be added. */ bool add_point(int64_t point) { require(this->la_velocity_size < HISTORY_SIZE); if (this->la_last_point_set) { // TODO Reenable this when we find the bug that causes some older // timestamps to show up after more recent ones. // require(this->la_last_point >= point); // Compute the message velocity. this->la_velocity[this->la_velocity_size] = ( this->la_last_point - point); // Find the range of velocities so we can normalize. this->la_min_velocity = std::min(this->la_min_velocity, this->la_velocity[this->la_velocity_size]); this->la_max_velocity = std::max(this->la_max_velocity, this->la_velocity[this->la_velocity_size]); this->la_velocity_size += 1; } this->la_last_point = point; this->la_last_point_set = true; return this->la_velocity_size < HISTORY_SIZE; }; /** * Get the average acceleration based on the time points we've received. * * @return The average message acceleration. */ double get_avg_accel() const { double avg_accel = 0, total_accel = 0; // Compute the range of values so we can normalize. double range = (double) (this->la_max_velocity - this->la_min_velocity); range = std::max(range, MIN_RANGE); for (int lpc = 0; lpc < (this->la_velocity_size - 1); lpc++) { double accel = ( (this->la_velocity[lpc] - this->la_min_velocity) / range - (this->la_velocity[lpc + 1] - this->la_min_velocity) / range); total_accel += accel; } if (this->la_velocity_size > 1) { avg_accel = total_accel / (double) (this->la_velocity_size - 1); } return avg_accel; }; /** * Compute the message rate direction. If the average acceleration is less * than a certain threshold, then we consider the rate to be steady. * Otherwise, the message rate is increasing or decreasing. * * @return The direction of the message rate. */ direction_t get_direction() const { double avg_accel = this->get_avg_accel(); direction_t retval; if (::fabs(avg_accel) <= THRESHOLD) { retval = A_STEADY; } else if (avg_accel < 0.0) { retval = A_ACCEL; } else { retval = A_DECEL; } return retval; }; private: /** * The amount of historical data to include in the average acceleration * computation. */ static const int HISTORY_SIZE = 8; /** * The minimum range of velocities seen. This value should limit false- * positives for small millisecond level fluctuations. */ static const double MIN_RANGE; static const double THRESHOLD; int64_t la_last_point; bool la_last_point_set; int64_t la_min_velocity; int64_t la_max_velocity; int64_t la_velocity[HISTORY_SIZE]; int la_velocity_size; }; #endif lnav-0.7.0/src/log_data_helper.hh000664 000765 000024 00000012243 12272736544 017167 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file log_data_helper.hh */ #ifndef __log_data_helper_hh #define __log_data_helper_hh #include #include #include "logfile_sub_source.hh" #include "data_parser.hh" #include "column_namer.hh" class log_data_helper { public: log_data_helper(logfile_sub_source &lss) : ldh_log_source(lss) { }; void clear() { this->ldh_file = NULL; this->ldh_msg.disown(); this->ldh_parser.reset(); this->ldh_scanner.reset(); this->ldh_namer.reset(); }; bool parse_line(vis_line_t line, bool allow_middle = false) { return this->parse_line(this->ldh_log_source.at(line), allow_middle); } bool parse_line(content_line_t line, bool allow_middle = false) { logfile::iterator ll; bool retval = false; this->ldh_source_line = this->ldh_line_index = line; this->ldh_file = this->ldh_log_source.find(this->ldh_line_index); ll = this->ldh_file->begin() + this->ldh_line_index; this->ldh_y_offset = 0; while (allow_middle && ll->is_continued()) { --ll; this->ldh_y_offset += 1; } this->ldh_line = ll; if (ll->is_continued()) { this->ldh_parser.reset(); this->ldh_scanner.reset(); this->ldh_namer.reset(); } else { log_format *format = this->ldh_file->get_format(); struct line_range body; string_attrs_t sa; this->ldh_file->read_full_message(ll, this->ldh_msg); this->ldh_line_values.clear(); format->annotate(this->ldh_msg, sa, this->ldh_line_values); body = find_string_attr_range(sa, &textview_curses::SA_BODY); if (body.lr_start == -1) { body.lr_start = this->ldh_msg.length(); body.lr_end = this->ldh_msg.length(); } this->ldh_scanner.reset(new data_scanner( this->ldh_msg, body.lr_start, body.lr_end)); this->ldh_parser.reset(new data_parser(this->ldh_scanner.get())); this->ldh_parser->parse(); this->ldh_namer.reset(new column_namer()); retval = true; } return retval; }; int get_line_bounds(size_t &line_index_out, size_t &line_end_index_out) const { int retval = 0; line_end_index_out = 0; do { const char *line_end; line_index_out = line_end_index_out; line_end = (const char *)memchr( this->ldh_msg.get_data() + line_index_out + 1, '\n', this->ldh_msg.length() - line_index_out - 1); if (line_end != NULL) { line_end_index_out = line_end - this->ldh_msg.get_data(); } else { line_end_index_out = std::string::npos; } retval += 1; } while (retval <= this->ldh_y_offset); if (line_end_index_out == std::string::npos) { line_end_index_out = this->ldh_msg.length(); } return retval; }; int get_value_line(const logline_value &lv) const { return std::count(this->ldh_msg.get_data(), this->ldh_msg.get_data() + lv.lv_origin.lr_start, '\n'); }; logfile_sub_source &ldh_log_source; content_line_t ldh_source_line; logfile *ldh_file; int ldh_y_offset; logfile::iterator ldh_line; shared_buffer_ref ldh_msg; content_line_t ldh_line_index; std::auto_ptr ldh_scanner; std::auto_ptr ldh_parser; std::auto_ptr ldh_namer; std::vector ldh_line_values; }; #endif lnav-0.7.0/src/log_data_table.hh000664 000765 000024 00000016775 12304655577 017017 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file log_data_table.hh * * XXX This file has become a dumping ground for code and needs to be broken up * a bit. */ #ifndef _log_data_table_hh #define _log_data_table_hh #include #include #include "lnav.hh" #include "logfile.hh" #include "data_parser.hh" #include "column_namer.hh" #include "log_vtab_impl.hh" class log_data_table : public log_vtab_impl { public: log_data_table(content_line_t template_line, std::string table_name = "logline") : log_vtab_impl(table_name), ldt_template_line(template_line), ldt_parent_column_count(0) { logfile *lf = lnav_data.ld_log_source.find(template_line); log_format *format = lf->get_format(); this->ldt_format_impl = lnav_data.ld_vtab_manager->lookup_impl(format->get_name()); }; void get_columns(std::vector &cols) { content_line_t cl_copy = this->ldt_template_line; logfile * lf = lnav_data.ld_log_source.find(cl_copy); struct line_range body; string_attrs_t sa; std::vector line_values; log_format *format = lf->get_format(); shared_buffer_ref line; if (this->ldt_format_impl != NULL) { this->ldt_format_impl->get_columns(cols); } this->ldt_parent_column_count = cols.size(); lf->read_full_message(lf->begin() + cl_copy, line); format->annotate(line, sa, line_values); body = find_string_attr_range(sa, &textview_curses::SA_BODY); if (body.lr_end == -1 || body.length() == 0) { this->ldt_schema_id.clear(); return; } data_scanner ds(line, body.lr_start, body.lr_end); data_parser dp(&ds); column_namer cn; dp.parse(); for (data_parser::element_list_t::iterator pair_iter = dp.dp_pairs.begin(); pair_iter != dp.dp_pairs.end(); ++pair_iter) { std::string key_str = dp.get_element_string( pair_iter->e_sub_elements->front()); std::string colname = cn.add_column(key_str); int sql_type = SQLITE3_TEXT; const char *collator = NULL; char * name; /* XXX LEAK */ name = strdup(colname.c_str()); switch (pair_iter->e_sub_elements->back().value_token()) { case DT_IPV4_ADDRESS: case DT_IPV6_ADDRESS: collator = "ipaddress"; break; case DT_NUMBER: sql_type = SQLITE_FLOAT; break; default: collator = "naturalnocase"; break; } cols.push_back(vtab_column(name, sql_type, collator)); } this->ldt_schema_id = dp.dp_schema_id; }; bool next(log_cursor &lc, logfile_sub_source &lss) { lc.lc_curr_line = lc.lc_curr_line + vis_line_t(1); lc.lc_sub_index = 0; if (lc.lc_curr_line == (int)lss.text_line_count()) { return true; } content_line_t cl; cl = lss.at(lc.lc_curr_line); logfile * lf = lss.find(cl); logfile::iterator lf_iter = lf->begin() + cl; if (lf_iter->is_continued()) { return false; } if (lf_iter->has_schema() && !lf_iter->match_schema(this->ldt_schema_id)) { return false; } string_attrs_t sa; struct line_range body; std::vector line_values; lf->read_full_message(lf_iter, this->ldt_current_line); lf->get_format()->annotate(this->ldt_current_line, sa, line_values); body = find_string_attr_range(sa, &textview_curses::SA_BODY); if (body.lr_end == -1 || body.length() == 0) { return false; } data_scanner ds(this->ldt_current_line, body.lr_start, body.lr_end); data_parser dp(&ds); dp.parse(); lf_iter->set_schema(dp.dp_schema_id); /* The cached schema ID in the log line is not complete, so we still */ /* need to check for a full match. */ if (dp.dp_schema_id != this->ldt_schema_id) { return false; } this->ldt_pairs.clear(); this->ldt_pairs.swap(dp.dp_pairs); return true; }; void extract(logfile *lf, shared_buffer_ref &line, std::vector &values) { int next_column = this->ldt_parent_column_count; this->ldt_format_impl->extract(lf, line, values); for (data_parser::element_list_t::iterator pair_iter = this->ldt_pairs.begin(); pair_iter != this->ldt_pairs.end(); ++pair_iter) { const data_parser::element &pvalue = pair_iter->get_pair_value(); switch (pvalue.value_token()) { case DT_NUMBER: { char scan_value[line.length() + 1]; double d = 0; memcpy(scan_value, line.get_data() + pvalue.e_capture.c_begin, pvalue.e_capture.length()); scan_value[line.length()] = '\0'; sscanf(scan_value, "%lf", &d); values.push_back(logline_value("", d)); } break; default: { shared_buffer_ref value_sbr; value_sbr.subset(line, pvalue.e_capture.c_begin, pvalue.e_capture.length()); values.push_back(logline_value("", logline_value::VALUE_TEXT, value_sbr)); break; } } values.back().lv_column = next_column++; } }; private: const content_line_t ldt_template_line; data_parser::schema_id_t ldt_schema_id; shared_buffer_ref ldt_current_line; data_parser::element_list_t ldt_pairs; log_vtab_impl *ldt_format_impl; int ldt_parent_column_count; }; #endif lnav-0.7.0/src/log_format.cc000664 000765 000024 00000111010 12313315543 016151 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include "yajlpp.hh" #include "sql_util.hh" #include "log_format.hh" #include "log_vtab_impl.hh" using namespace std; /* * Supported formats: * generic * syslog * apache * tcpdump * strace * vstrace * csv (?) * file system (?) * plugins * vmstat * iostat */ string_attr_type logline::L_PREFIX; string_attr_type logline::L_TIMESTAMP; string_attr_type logline::L_FILE; string_attr_type logline::L_PARTITION; const char *logline::level_names[LEVEL__MAX + 1] = { "unknown", "trace", "debug", "info", "warning", "error", "critical", "fatal", NULL }; static int strncasestr_i(const char *s1, const char *s2, size_t len) { return strcasestr(s1, s2) == NULL; } logline::level_t logline::string2level(const char *levelstr, size_t len, bool exact) { logline::level_t retval = logline::LEVEL_UNKNOWN; int (*cmpfunc)(const char *, const char *, size_t); require(len == (size_t)-1 || (len != (size_t)-1 && exact)); if (len == (size_t)-1) len = strlen(levelstr); if (exact) { cmpfunc = strncasecmp; } else{ cmpfunc = strncasestr_i; } if (((len == 1) || ((len > 1) && (levelstr[1] == ' '))) && (retval = abbrev2level(levelstr, len)) != LEVEL_UNKNOWN) { return retval; } if (cmpfunc(levelstr, "TRACE", len) == 0) { retval = logline::LEVEL_TRACE; } else if (cmpfunc(levelstr, "VERBOSE", len) == 0) { retval = logline::LEVEL_DEBUG; } else if (cmpfunc(levelstr, "DEBUG", len) == 0) { retval = logline::LEVEL_DEBUG; } else if (cmpfunc(levelstr, "INFO", len) == 0) { retval = logline::LEVEL_INFO; } else if (cmpfunc(levelstr, "WARNING", len) == 0) { retval = logline::LEVEL_WARNING; } else if (cmpfunc(levelstr, "ERROR", len) == 0) { retval = logline::LEVEL_ERROR; } else if (cmpfunc(levelstr, "CRITICAL", len) == 0) { retval = logline::LEVEL_CRITICAL; } else if (cmpfunc(levelstr, "FATAL", len) == 0) { retval = logline::LEVEL_FATAL; } return retval; } logline::level_t logline::abbrev2level(const char *levelstr, size_t len) { if (len == -1) { len = strlen(levelstr); } if (len == 0) { return LEVEL_UNKNOWN; } switch (toupper(levelstr[0])) { case 'T': return LEVEL_TRACE; case 'D': return LEVEL_DEBUG; case 'I': return LEVEL_INFO; case 'W': return LEVEL_WARNING; case 'E': return LEVEL_ERROR; case 'C': return LEVEL_CRITICAL; case 'F': return LEVEL_FATAL; } return LEVEL_UNKNOWN; } int logline::levelcmp(const char *l1, size_t l1_len, const char *l2, size_t l2_len) { return abbrev2level(l1, l1_len) - abbrev2level(l2, l2_len); } const char *logline_value::value_names[VALUE__MAX] = { "null", "text", "int", "float", "bool" }; logline_value::kind_t logline_value::string2kind(const char *kindstr) { if (strcmp(kindstr, "string") == 0) { return VALUE_TEXT; } else if (strcmp(kindstr, "integer") == 0) { return VALUE_INTEGER; } else if (strcmp(kindstr, "float") == 0) { return VALUE_FLOAT; } else if (strcmp(kindstr, "boolean") == 0) { return VALUE_BOOLEAN; } return VALUE_UNKNOWN; } vector log_format::lf_root_formats; vector &log_format::get_root_formats(void) { return lf_root_formats; } static bool next_format(const std::vector &patterns, int &index, int &locked_index) { bool retval = true; if (locked_index == -1) { index += 1; if (index >= (int)patterns.size()) { retval = false; } } else if (index == locked_index) { retval = false; } else { index = locked_index; } return retval; } const char *log_format::log_scanf(const char *line, const char *fmt[], int expected_matches, const char *time_fmt[], char *time_dest, struct tm *tm_out, struct timeval &tv_out, ...) { int curr_fmt = -1; const char * retval = NULL; va_list args; while (next_format(fmt, curr_fmt, this->lf_fmt_lock)) { va_start(args, tv_out); int matches; time_dest[0] = '\0'; matches = vsscanf(line, fmt[curr_fmt], args); if (matches < expected_matches) { retval = NULL; continue; } if (time_dest[0] == '\0') { retval = NULL; } else { retval = this->lf_date_time.scan(time_dest, time_fmt, tm_out, tv_out); if (retval) { this->lf_fmt_lock = curr_fmt; break; } } va_end(args); } return retval; } /* * XXX This needs some cleanup. */ struct json_log_userdata { json_log_userdata() : jlu_sub_line_count(1) { }; external_log_format *jlu_format; const logline *jlu_line; logline *jlu_base_line; int jlu_sub_line_count; yajl_handle jlu_handle; const char *jlu_line_value; size_t jlu_sub_start; }; struct json_field_cmp { json_field_cmp(external_log_format::json_log_field type, const std::string &name) : jfc_type(type), jfc_field_name(name) { }; bool operator()(const external_log_format::json_format_element &jfe) const { return (this->jfc_type == jfe.jfe_type && this->jfc_field_name == jfe.jfe_value); }; external_log_format::json_log_field jfc_type; const std::string &jfc_field_name; }; static int read_json_field(yajlpp_parse_context *ypc, const unsigned char *str, size_t len); static int read_json_null(yajlpp_parse_context *ypc) { json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; vector &line_format = jlu->jlu_format->jlf_line_format; string field_name = ypc->get_path_fragment(0); if (find_if(line_format.begin(), line_format.end(), json_field_cmp(external_log_format::JLF_VARIABLE, field_name)) == line_format.end()) { jlu->jlu_sub_line_count += 1; } return 1; } static int read_json_bool(yajlpp_parse_context *ypc, int val) { json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; vector &line_format = jlu->jlu_format->jlf_line_format; string field_name = ypc->get_path_fragment(0); if (find_if(line_format.begin(), line_format.end(), json_field_cmp(external_log_format::JLF_VARIABLE, field_name)) == line_format.end()) { jlu->jlu_sub_line_count += 1; } return 1; } static int read_json_int(yajlpp_parse_context *ypc, long long val) { json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; vector &line_format = jlu->jlu_format->jlf_line_format; string field_name = ypc->get_path_fragment(0); if (field_name == jlu->jlu_format->lf_timestamp_field) { long long divisor = jlu->jlu_format->elf_timestamp_divisor; struct timeval tv; tv.tv_sec = val / divisor; tv.tv_usec = (val % divisor) * (1000000.0 / divisor); jlu->jlu_base_line->set_time(tv); } else if (find_if(line_format.begin(), line_format.end(), json_field_cmp(external_log_format::JLF_VARIABLE, field_name)) == line_format.end()) { jlu->jlu_sub_line_count += 1; } return 1; } static int read_json_double(yajlpp_parse_context *ypc, double val) { json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; vector &line_format = jlu->jlu_format->jlf_line_format; string field_name = ypc->get_path_fragment(0); if (field_name == jlu->jlu_format->lf_timestamp_field) { double divisor = jlu->jlu_format->elf_timestamp_divisor; struct timeval tv; tv.tv_sec = val / divisor; tv.tv_usec = fmod(val, divisor) * (1000000.0 / divisor); jlu->jlu_base_line->set_time(tv); } else if (find_if(line_format.begin(), line_format.end(), json_field_cmp(external_log_format::JLF_VARIABLE, field_name)) == line_format.end()) { jlu->jlu_sub_line_count += 1; } return 1; } static int json_array_start(void *ctx) { yajlpp_parse_context *ypc = (yajlpp_parse_context *)ctx; json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; vector &line_format = jlu->jlu_format->jlf_line_format; if (ypc->ypc_path_index_stack.size() == 2) { string field_name = ypc->get_path_fragment(0); if (find_if(line_format.begin(), line_format.end(), json_field_cmp(external_log_format::JLF_VARIABLE, field_name)) == line_format.end()) { jlu->jlu_sub_line_count += 1; } jlu->jlu_sub_start = yajl_get_bytes_consumed(jlu->jlu_handle) - 1; } return 1; } static int json_array_end(void *ctx) { yajlpp_parse_context *ypc = (yajlpp_parse_context *)ctx; json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; if (ypc->ypc_path_index_stack.size() == 1) { string field_name = ypc->get_path_fragment(0); size_t sub_end = yajl_get_bytes_consumed(jlu->jlu_handle); tmp_shared_buffer tsb(&jlu->jlu_line_value[jlu->jlu_sub_start], sub_end - jlu->jlu_sub_start); jlu->jlu_format->jlf_line_values.push_back( logline_value(field_name, tsb.tsb_ref)); } return 1; } static struct json_path_handler json_log_handlers[] = { json_path_handler("^/\\w+$"). add_cb(read_json_null). add_cb(read_json_bool). add_cb(read_json_int). add_cb(read_json_double). add_cb(read_json_field), json_path_handler() }; static int rewrite_json_field(yajlpp_parse_context *ypc, const unsigned char *str, size_t len); static int rewrite_json_null(yajlpp_parse_context *ypc) { json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; string field_name = ypc->get_path_fragment(0); jlu->jlu_format->jlf_line_values.push_back(logline_value(field_name)); return 1; } static int rewrite_json_bool(yajlpp_parse_context *ypc, int val) { json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; string field_name = ypc->get_path_fragment(0); jlu->jlu_format->jlf_line_values.push_back(logline_value(field_name, (bool)val)); return 1; } static int rewrite_json_int(yajlpp_parse_context *ypc, long long val) { json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; string field_name = ypc->get_path_fragment(0); jlu->jlu_format->jlf_line_values.push_back(logline_value(field_name, (int64_t)val)); return 1; } static int rewrite_json_double(yajlpp_parse_context *ypc, double val) { json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; string field_name = ypc->get_path_fragment(0); jlu->jlu_format->jlf_line_values.push_back(logline_value(field_name, val)); return 1; } static struct json_path_handler json_log_rewrite_handlers[] = { json_path_handler("^/\\w+$"). add_cb(rewrite_json_null). add_cb(rewrite_json_bool). add_cb(rewrite_json_int). add_cb(rewrite_json_double). add_cb(rewrite_json_field), json_path_handler() }; bool external_log_format::scan(std::vector &dst, off_t offset, char *prefix, int len) { if (this->jlf_json) { auto_mem handle(yajl_free); yajlpp_parse_context &ypc = *(this->jlf_parse_context); logline ll(offset, 0, 0, logline::LEVEL_INFO); json_log_userdata jlu; bool retval = false; handle = yajl_alloc(&this->jlf_parse_context->ypc_callbacks, NULL, this->jlf_parse_context.get()); ypc.reset(json_log_handlers); ypc.ypc_userdata = &jlu; ypc.ypc_ignore_unused = true; ypc.ypc_alt_callbacks.yajl_start_array = json_array_start; ypc.ypc_alt_callbacks.yajl_start_map = json_array_start; jlu.jlu_format = this; jlu.jlu_base_line = ≪ jlu.jlu_line_value = prefix; jlu.jlu_handle = handle; if (yajl_parse(handle.in(), (const unsigned char *)prefix, len) == yajl_status_ok && yajl_complete_parse(handle.in()) == yajl_status_ok) { for (int lpc = 0; lpc < jlu.jlu_sub_line_count; lpc++) { ll.set_sub_offset(lpc); if (lpc > 0) { ll.set_level((logline::level_t) (ll.get_level() | logline::LEVEL_CONTINUED)); } dst.push_back(ll); } retval = true; } return retval; } pcre_input pi(prefix, 0, len); pcre_context_static<128> pc; bool retval = false; int curr_fmt = -1; while (next_format(this->elf_pattern_order, curr_fmt, this->lf_fmt_lock)) { pcrepp *pat = this->elf_pattern_order[curr_fmt]->p_pcre; if (!pat->match(pc, pi)) { continue; } if (this->lf_fmt_lock == -1) { this->lf_timestamp_field_index = pat->name_index( this->lf_timestamp_field); this->elf_level_field_index = pat->name_index( this->elf_level_field); } pcre_context::capture_t *ts = pc[this->lf_timestamp_field_index]; pcre_context::capture_t *level_cap = pc[this->elf_level_field_index]; const char *ts_str = pi.get_substr_start(ts); const char *last; struct tm log_time_tm; struct timeval log_tv; logline::level_t level = logline::LEVEL_INFO; if ((last = this->lf_date_time.scan(ts_str, NULL, &log_time_tm, log_tv)) == NULL) { continue; } if (level_cap != NULL && level_cap->c_begin != -1) { pcre_context_static<128> pc_level; pcre_input pi_level(pi.get_substr_start(level_cap), 0, level_cap->length()); for (std::map::iterator iter = this->elf_level_patterns.begin(); iter != this->elf_level_patterns.end(); ++iter) { if (iter->second.lp_pcre->match(pc_level, pi_level)) { level = iter->first; break; } } } this->check_for_new_year(dst, log_tv); dst.push_back(logline(offset, log_tv, level)); this->lf_fmt_lock = curr_fmt; retval = true; break; } return retval; } void external_log_format::annotate(shared_buffer_ref &line, string_attrs_t &sa, std::vector &values) const { pcre_context_static<128> pc; pcre_input pi(line.get_data(), 0, line.length()); struct line_range lr; pcre_context::capture_t *cap; if (this->jlf_json) { values = this->jlf_line_values; sa = this->jlf_line_attrs; return; } pattern &pat = *this->elf_pattern_order[this->lf_fmt_lock]; if (!pat.p_pcre->match(pc, pi)) { return; } cap = pc[this->lf_timestamp_field_index]; lr.lr_start = cap->c_begin; lr.lr_end = cap->c_end; sa.push_back(string_attr(lr, &logline::L_TIMESTAMP)); cap = pc[this->elf_body_field_index]; if (cap != NULL && cap->c_begin != -1) { lr.lr_start = cap->c_begin; lr.lr_end = cap->c_end; } else { lr.lr_start = line.length(); lr.lr_end = line.length(); } sa.push_back(string_attr(lr, &textview_curses::SA_BODY)); view_colors &vc = view_colors::singleton(); for (size_t lpc = 0; lpc < pat.p_value_by_index.size(); lpc++) { const value_def &vd = pat.p_value_by_index[lpc]; const struct scaling_factor *scaling = NULL; pcre_context::capture_t *cap = pc[vd.vd_index]; shared_buffer_ref field; if (vd.vd_unit_field_index >= 0) { pcre_context::iterator unit_cap = pc[vd.vd_unit_field_index]; if (unit_cap != NULL && unit_cap->c_begin != -1) { std::string unit_val = pi.get_substr(unit_cap); std::map::const_iterator unit_iter; unit_iter = vd.vd_unit_scaling.find(unit_val); if (unit_iter != vd.vd_unit_scaling.end()) { const struct scaling_factor &sf = unit_iter->second; scaling = &sf; } } } field.subset(line, cap->c_begin, cap->length()); values.push_back(logline_value(vd.vd_name, vd.vd_kind, field, vd.vd_identifier, scaling, vd.vd_column, cap->c_begin, cap->c_end)); if (pc[vd.vd_index]->c_begin != -1 && vd.vd_identifier) { lr.lr_start = pc[vd.vd_index]->c_begin; lr.lr_end = pc[vd.vd_index]->c_end; sa.push_back(string_attr(lr, &view_curses::VC_STYLE, vc.attrs_for_ident(pi.get_substr_start(pc[vd.vd_index]), lr.length()))); } } } static int read_json_field(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; vector &line_format = jlu->jlu_format->jlf_line_format; string field_name = ypc->get_path_fragment(0); struct tm tm_out; struct timeval tv_out; if (field_name == jlu->jlu_format->lf_timestamp_field) { jlu->jlu_format->lf_date_time.scan((const char *)str, NULL, &tm_out, tv_out); jlu->jlu_base_line->set_time(tv_out); } else if (field_name == jlu->jlu_format->elf_level_field) { jlu->jlu_base_line->set_level(logline::string2level((const char *)str, len, true)); } else { if (find_if(line_format.begin(), line_format.end(), json_field_cmp(external_log_format::JLF_VARIABLE, field_name)) == line_format.end()) { jlu->jlu_sub_line_count += 1; } for (size_t lpc = 0; lpc < len; lpc++) { if (str[lpc] == '\n') { jlu->jlu_sub_line_count += 1; } } } return 1; } static int rewrite_json_field(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { json_log_userdata *jlu = (json_log_userdata *)ypc->ypc_userdata; string field_name = ypc->get_path_fragment(0); if (field_name == jlu->jlu_format->lf_timestamp_field) { char time_buf[64]; sql_strftime(time_buf, sizeof(time_buf), jlu->jlu_line->get_timeval(), 'T'); tmp_shared_buffer tsb(time_buf); jlu->jlu_format->jlf_line_values.push_back(logline_value(field_name, tsb.tsb_ref)); } else { tmp_shared_buffer tsb((const char *)str, len); if (field_name == jlu->jlu_format->elf_body_field) { jlu->jlu_format->jlf_line_values.push_back(logline_value("body", tsb.tsb_ref)); } jlu->jlu_format->jlf_line_values.push_back(logline_value(field_name, tsb.tsb_ref)); } return 1; } void external_log_format::get_subline(const logline &ll, shared_buffer_ref &sbr) { if (!this->jlf_json) { return; } if (this->jlf_cached_offset != ll.get_offset()) { auto_mem handle(yajl_free); yajlpp_parse_context &ypc = *(this->jlf_parse_context); view_colors &vc = view_colors::singleton(); json_log_userdata jlu; this->jlf_share_manager.invalidate_refs(); this->jlf_cached_line.clear(); this->jlf_line_values.clear(); this->jlf_line_offsets.clear(); this->jlf_line_attrs.clear(); handle = yajl_alloc(&this->jlf_parse_context->ypc_callbacks, NULL, this->jlf_parse_context.get()); ypc.reset(json_log_rewrite_handlers); ypc.ypc_userdata = &jlu; ypc.ypc_ignore_unused = true; ypc.ypc_alt_callbacks.yajl_start_array = json_array_start; ypc.ypc_alt_callbacks.yajl_end_array = json_array_end; ypc.ypc_alt_callbacks.yajl_start_map = json_array_start; ypc.ypc_alt_callbacks.yajl_end_map = json_array_end; jlu.jlu_format = this; jlu.jlu_line = ≪ jlu.jlu_handle = handle; jlu.jlu_line_value = sbr.get_data(); yajl_status parse_status = yajl_parse(handle.in(), (const unsigned char *)sbr.get_data(), sbr.length()); if (parse_status == yajl_status_ok && yajl_complete_parse(handle.in()) == yajl_status_ok) { std::vector::iterator lv_iter; std::vector::iterator iter; bool used_values[this->jlf_line_values.size()]; struct line_range lr; ostringstream lines; memset(used_values, 0, sizeof(used_values)); for (lv_iter = this->jlf_line_values.begin(); lv_iter != this->jlf_line_values.end(); ++lv_iter) { map::iterator vd_iter; vd_iter = this->elf_value_defs.find(lv_iter->lv_name); if (vd_iter != this->elf_value_defs.end()) { lv_iter->lv_identifier = vd_iter->second.vd_identifier; lv_iter->lv_column = vd_iter->second.vd_column; } } for (iter = this->jlf_line_format.begin(); iter != this->jlf_line_format.end(); ++iter) { switch (iter->jfe_type) { case JLF_CONSTANT: lines << iter->jfe_default_value; break; case JLF_VARIABLE: lv_iter = find_if(this->jlf_line_values.begin(), this->jlf_line_values.end(), logline_value_cmp(&iter->jfe_value)); if (lv_iter != this->jlf_line_values.end()) { string str = lv_iter->to_string(); size_t nl_pos = str.find('\n'); lr.lr_start = lines.tellp(); lines << str; if (nl_pos == string::npos) lr.lr_end = lines.tellp(); else lr.lr_end = lr.lr_start + nl_pos; if (lv_iter->lv_name == this->lf_timestamp_field) { this->jlf_line_attrs.push_back( string_attr(lr, &logline::L_TIMESTAMP)); } else if (lv_iter->lv_name == this->elf_body_field) { this->jlf_line_attrs.push_back( string_attr(lr, &textview_curses::SA_BODY)); } else if (lv_iter->lv_identifier) { this->jlf_line_attrs.push_back( string_attr(lr, &view_curses::VC_STYLE, vc.attrs_for_ident(str.c_str(), lr.length()))); } lv_iter->lv_origin = lr; used_values[distance(this->jlf_line_values.begin(), lv_iter)] = true; } else if (iter->jfe_value == "__timestamp__") { struct line_range lr; char ts[64]; sql_strftime(ts, sizeof(ts), ll.get_timeval(), 'T'); lr.lr_start = lines.tellp(); lines << ts; lr.lr_end = lines.tellp(); this->jlf_line_attrs.push_back( string_attr(lr, &logline::L_TIMESTAMP)); } else { lines << iter->jfe_default_value; } break; } } lines << endl; for (size_t lpc = 0; lpc < this->jlf_line_values.size(); lpc++) { logline_value &lv = this->jlf_line_values[lpc]; if (used_values[lpc] || lv.lv_name == this->lf_timestamp_field || lv.lv_name == "body" || lv.lv_name == this->elf_level_field) { continue; } const std::string str = lv.to_string(); size_t curr_pos = 0, nl_pos, line_len = -1; lv.lv_origin.lr_start = lines.tellp(); do { nl_pos = str.find('\n', curr_pos); if (nl_pos != std::string::npos) { line_len = nl_pos - curr_pos; } lines << " " << lv.lv_name << ": " << str.substr(curr_pos, line_len) << endl; curr_pos = nl_pos + 1; line_len = -1; } while (nl_pos != std::string::npos && nl_pos < str.size()); lv.lv_origin.lr_end = lines.tellp(); } this->jlf_cached_line = lines.str(); this->jlf_line_offsets.push_back(0); for (size_t lpc = 0; lpc < this->jlf_cached_line.size(); lpc++) { if (this->jlf_cached_line[lpc] == '\n') { this->jlf_line_offsets.push_back(lpc); } } this->jlf_line_offsets.push_back(this->jlf_cached_line.size()); } this->jlf_cached_offset = ll.get_offset(); } off_t this_off, next_off; this_off = this->jlf_line_offsets[ll.get_sub_offset()]; if (this->jlf_cached_line[this_off] == '\n') this_off += 1; next_off = this->jlf_line_offsets[ll.get_sub_offset() + 1]; sbr.share(this->jlf_share_manager, (char *)this->jlf_cached_line.c_str() + this_off, next_off - this_off); } void external_log_format::build(std::vector &errors) { try { this->elf_filename_pcre = new pcrepp(this->elf_file_pattern.c_str()); } catch (const pcrepp::error &e) { errors.push_back("error:" + this->elf_name + ".file-pattern:" + e.what()); } for (std::map::iterator iter = this->elf_patterns.begin(); iter != this->elf_patterns.end(); ++iter) { try { iter->second.p_pcre = new pcrepp(iter->second.p_string.c_str()); } catch (const pcrepp::error &e) { errors.push_back("error:" + this->elf_name + ".regex[]" + ":" + e.what()); continue; } for (pcre_named_capture::iterator name_iter = iter->second.p_pcre->named_begin(); name_iter != iter->second.p_pcre->named_end(); ++name_iter) { std::map::iterator value_iter; value_iter = this->elf_value_defs.find(std::string(name_iter->pnc_name)); if (value_iter != this->elf_value_defs.end()) { value_def &vd = value_iter->second; vd.vd_index = name_iter->index(); vd.vd_unit_field_index = iter->second.p_pcre->name_index(vd.vd_unit_field.c_str()); if (vd.vd_column == -1) { vd.vd_column = this->elf_column_count++; } iter->second.p_value_by_index.push_back(vd); } } stable_sort(iter->second.p_value_by_index.begin(), iter->second.p_value_by_index.end()); this->elf_pattern_order.push_back(&iter->second); } if (this->jlf_json) { if (!this->elf_patterns.empty()) { errors.push_back("error:" + this->elf_name + ": JSON logs cannot have regexes"); } if (this->jlf_json) { this->jlf_parse_context.reset(new yajlpp_parse_context(this->elf_name)); } } else { if (this->elf_patterns.empty()) { errors.push_back("error:" + this->elf_name + ": no regexes specified for format"); } } for (std::map::iterator iter = this->elf_level_patterns.begin(); iter != this->elf_level_patterns.end(); ++iter) { try { iter->second.lp_pcre = new pcrepp(iter->second.lp_regex.c_str()); } catch (const pcrepp::error &e) { errors.push_back("error:" + this->elf_name + ".level:" + e.what()); } } for (std::map::iterator iter = this->elf_value_defs.begin(); iter != this->elf_value_defs.end(); ++iter) { std::vector::iterator act_iter; if (iter->second.vd_column == -1) { iter->second.vd_column = this->elf_column_count++; } for (act_iter = iter->second.vd_action_list.begin(); act_iter != iter->second.vd_action_list.end(); ++act_iter) { if (this->lf_action_defs.find(*act_iter) == this->lf_action_defs.end()) { errors.push_back("error:" + this->elf_name + ":" + iter->first + ": cannot find action -- " + (*act_iter)); } } } if (!this->jlf_json && this->elf_samples.empty()) { errors.push_back("error:" + this->elf_name + ":no sample logs provided, all formats must have samples"); } for (std::vector::iterator iter = this->elf_samples.begin(); iter != this->elf_samples.end(); ++iter) { pcre_context_static<128> pc; pcre_input pi(iter->s_line); bool found = false; for (std::vector::iterator pat_iter = this->elf_pattern_order.begin(); pat_iter != this->elf_pattern_order.end() && !found; ++pat_iter) { pattern &pat = *(*pat_iter); if (!pat.p_pcre) continue; if (pat.p_pcre->match(pc, pi)) { const char *ts = pi.get_substr_start( pc[this->lf_timestamp_field]); date_time_scanner dts; struct timeval tv; struct tm tm; if (dts.scan(ts, NULL, &tm, tv) != NULL) { found = true; break; } } } if (!found) { errors.push_back("error:" + this->elf_name + ":invalid sample -- " + iter->s_line); for (std::vector::iterator pat_iter = this->elf_pattern_order.begin(); pat_iter != this->elf_pattern_order.end(); ++pat_iter) { pattern &pat = *(*pat_iter); if (!pat.p_pcre) continue; std::string line_partial = iter->s_line; while (!line_partial.empty()) { pcre_input pi_partial(line_partial); if (pat.p_pcre->match(pc, pi_partial, PCRE_PARTIAL)) { errors.push_back("error:" + this->elf_name + ":partial sample matched -- " + line_partial); break; } line_partial = line_partial.substr(0, line_partial.size() - 1); } if (line_partial.empty()) { errors.push_back("error:" + this->elf_name + ":no partial match found"); } } } } } class external_log_table : public log_vtab_impl { public: external_log_table(const external_log_format &elf) : log_vtab_impl(elf.get_name()), elt_format(elf) { }; void get_columns(vector &cols) { std::map::const_iterator iter; const external_log_format &elf = this->elt_format; cols.resize(elf.elf_value_defs.size()); for (iter = elf.elf_value_defs.begin(); iter != elf.elf_value_defs.end(); ++iter) { const external_log_format::value_def &vd = iter->second; int type; switch (vd.vd_kind) { case logline_value::VALUE_NULL: case logline_value::VALUE_TEXT: type = SQLITE3_TEXT; break; case logline_value::VALUE_FLOAT: type = SQLITE_FLOAT; break; case logline_value::VALUE_BOOLEAN: case logline_value::VALUE_INTEGER: type = SQLITE_INTEGER; break; case logline_value::VALUE_UNKNOWN: case logline_value::VALUE__MAX: ensure(0); break; } cols[vd.vd_column].vc_name = vd.vd_name.c_str(); cols[vd.vd_column].vc_type = type; cols[vd.vd_column].vc_collator = vd.vd_collate.c_str(); } }; void get_foreign_keys(std::vector &keys_inout) { std::map::const_iterator iter; log_vtab_impl::get_foreign_keys(keys_inout); for (iter = this->elt_format.elf_value_defs.begin(); iter != this->elt_format.elf_value_defs.end(); ++iter) { if (iter->second.vd_foreign_key) { keys_inout.push_back(iter->first); } } }; const external_log_format &elt_format; }; log_vtab_impl *external_log_format::get_vtab_impl(void) const { return new external_log_table(*this); } /* XXX */ #include "log_format_impls.cc" lnav-0.7.0/src/log_format.hh000664 000765 000024 00000054763 12311333336 016206 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file log_format.hh */ #ifndef __log_format_hh #define __log_format_hh #include #include #include #define __STDC_FORMAT_MACROS #include #include #include #include #include #include #include #include "pcrepp.hh" #include "yajlpp.hh" #include "lnav_log.hh" #include "lnav_util.hh" #include "byte_array.hh" #include "view_curses.hh" #include "shared_buffer.hh" class logline; class logfile_filter { public: typedef enum { MAYBE, INCLUDE, EXCLUDE, LFT__MAX, LFT__MASK = (MAYBE|INCLUDE|EXCLUDE) } type_t; logfile_filter(type_t type, const std::string id) : lf_enabled(true), lf_type(type), lf_id(id) { }; virtual ~logfile_filter() { }; type_t get_type(void) const { return this->lf_type; }; std::string get_id(void) const { return this->lf_id; }; bool is_enabled(void) { return this->lf_enabled; }; void enable(void) { this->lf_enabled = true; }; void disable(void) { this->lf_enabled = false; }; virtual bool matches(const logline &ll, const std::string &line) = 0; virtual std::string to_command(void) = 0; bool operator==(const std::string &rhs) { return this->lf_id == rhs; }; protected: bool lf_enabled; type_t lf_type; std::string lf_id; }; typedef std::vector filter_stack_t; /** * Metadata for a single line in a log file. */ class logline { public: static string_attr_type L_PREFIX; static string_attr_type L_TIMESTAMP; static string_attr_type L_FILE; static string_attr_type L_PARTITION; /** * The logging level identifiers for a line(s). */ typedef enum { LEVEL_UNKNOWN, LEVEL_TRACE, LEVEL_DEBUG, LEVEL_INFO, LEVEL_WARNING, LEVEL_ERROR, LEVEL_CRITICAL, LEVEL_FATAL, LEVEL__MAX, LEVEL_MARK = 0x40, /*< Bookmarked line. */ LEVEL_CONTINUED = 0x80, /*< Continuation of multiline entry. */ /** Mask of flags for the level field. */ LEVEL__FLAGS = (LEVEL_MARK | LEVEL_CONTINUED) } level_t; static const char *level_names[LEVEL__MAX + 1]; static level_t string2level(const char *levelstr, size_t len = -1, bool exact = false); static level_t abbrev2level(const char *levelstr, size_t len = -1); static int levelcmp(const char *l1, size_t l1_len, const char *l2, size_t l2_len); /** * Construct a logline object with the given values. * * @param off The offset of the line in the file. * @param t The timestamp for the line. * @param millis The millisecond timestamp for the line. * @param l The logging level. */ logline(off_t off, time_t t, uint16_t millis, level_t l) : ll_offset(off), ll_time(t), ll_millis(millis), ll_level(l), ll_filter_state(logfile_filter::MAYBE), ll_sub_offset(0) { memset(this->ll_schema, 0, sizeof(this->ll_schema)); }; logline(off_t off, const struct timeval &tv, level_t l, uint8_t m = 0) : ll_offset(off), ll_level(l), ll_filter_state(logfile_filter::MAYBE), ll_sub_offset(0) { this->set_time(tv); memset(this->ll_schema, 0, sizeof(this->ll_schema)); }; /** @return The offset of the line in the file. */ off_t get_offset() const { return this->ll_offset; }; uint16_t get_sub_offset() const { return this->ll_sub_offset; }; void set_sub_offset(uint16_t suboff) { this->ll_sub_offset = suboff; }; /** @return The timestamp for the line. */ time_t get_time() const { return this->ll_time; }; void set_time(time_t t) { this->ll_time = t; }; /** @return The millisecond timestamp for the line. */ uint16_t get_millis() const { return this->ll_millis; }; void set_millis(uint16_t m) { this->ll_millis = m; }; uint64_t get_time_in_millis() const { return (this->ll_time * 1000ULL + (uint64_t) this->ll_millis); }; struct timeval get_timeval() const { struct timeval retval = { this->ll_time, this->ll_millis * 1000 }; return retval; }; void set_time(const struct timeval &tv) { this->ll_time = tv.tv_sec; this->ll_millis = tv.tv_usec / 1000; }; void set_mark(bool val) { if (val) { this->ll_level |= LEVEL_MARK; } else { this->ll_level &= ~LEVEL_MARK; } }; bool is_marked(void) const { return this->ll_level & LEVEL_MARK; }; /** @param l The logging level. */ void set_level(level_t l) { this->ll_level = l; }; /** @return The logging level. */ level_t get_level() const { return (level_t)(this->ll_level & 0xff); }; const char *get_level_name() const { return level_names[this->ll_level & 0x0f]; }; bool is_continued(void) const { return this->get_level() & LEVEL_CONTINUED; }; uint8_t get_filter_generation(void) const { return this->ll_filter_state >> 2; }; logfile_filter::type_t get_filter_state(void) const { return (logfile_filter::type_t)(this->ll_filter_state & logfile_filter::LFT__MASK); }; void set_filter_state(uint8_t generation, logfile_filter::type_t filter) { this->ll_filter_state = (generation << 2) | filter; }; /** * @return True if there is a schema value set for this log line. */ bool has_schema(void) const { return (this->ll_schema[0] != 0 || this->ll_schema[1] != 0 || this->ll_schema[2] != 0 || this->ll_schema[3] != 0); }; /** * Set the "schema" for this log line. The schema ID is used to match log * lines that have a similar format when generating the logline table. The * schema is set lazily so that startup is faster. * * @param ba The SHA-1 hash of the constant parts of this log line. */ void set_schema(const byte_array<2, uint64_t> &ba) { memcpy(this->ll_schema, ba.in(), sizeof(this->ll_schema)); }; /** * Perform a partial match of the given schema against this log line. * Storing the full schema is not practical, so we just keep the first four * bytes. * * @param ba The SHA-1 hash of the constant parts of a log line. * @return True if the first four bytes of the given schema match the * schema stored in this log line. */ bool match_schema(const byte_array<2, uint64_t> &ba) const { return memcmp(this->ll_schema, ba.in(), sizeof(this->ll_schema)) == 0; } /** * Compare loglines based on their timestamp. */ bool operator<(const logline &rhs) const { return this->ll_time < rhs.ll_time || (this->ll_time == rhs.ll_time && this->ll_millis < rhs.ll_millis); }; bool operator<(const time_t &rhs) const { return this->ll_time < rhs; }; bool operator<(const struct timeval &rhs) const { return ((this->ll_time < rhs.tv_sec) || (this->ll_millis < (rhs.tv_usec / 1000))); }; private: off_t ll_offset; time_t ll_time; uint16_t ll_millis; uint8_t ll_level; uint8_t ll_filter_state; uint16_t ll_sub_offset; char ll_schema[4]; }; enum scale_op_t { SO_IDENTITY, SO_MULTIPLY, SO_DIVIDE }; struct scaling_factor { scaling_factor() : sf_op(SO_IDENTITY), sf_value(1) { }; template void scale(T &val) const { switch (this->sf_op) { case SO_IDENTITY: break; case SO_DIVIDE: val = val / (T)this->sf_value; break; case SO_MULTIPLY: val = val * (T)this->sf_value; break; } } scale_op_t sf_op; double sf_value; }; class logline_value { public: enum kind_t { VALUE_UNKNOWN = -1, VALUE_NULL, VALUE_TEXT, VALUE_INTEGER, VALUE_FLOAT, VALUE_BOOLEAN, VALUE__MAX }; static const char *value_names[VALUE__MAX]; static kind_t string2kind(const char *kindstr); logline_value(std::string name) : lv_name(name), lv_kind(VALUE_NULL), lv_identifier(), lv_column(-1) { }; logline_value(std::string name, bool b) : lv_name(name), lv_kind(VALUE_BOOLEAN), lv_number((int64_t)(b ? 1 : 0)), lv_identifier(), lv_column(-1) { }; logline_value(std::string name, int64_t i) : lv_name(name), lv_kind(VALUE_INTEGER), lv_number(i), lv_identifier(), lv_column(-1) { }; logline_value(std::string name, double i) : lv_name(name), lv_kind(VALUE_FLOAT), lv_number(i), lv_identifier(), lv_column(-1) { }; logline_value(std::string name, shared_buffer_ref &sbr) : lv_name(name), lv_kind(VALUE_TEXT), lv_sbr(sbr), lv_identifier(), lv_column(-1) { }; logline_value(std::string name, kind_t kind, shared_buffer_ref &sbr, bool ident=false, const scaling_factor *scaling=NULL, int col=-1, int start=-1, int end=-1) : lv_name(name), lv_kind(kind), lv_identifier(ident), lv_column(col), lv_origin(start, end) { if (sbr.get_data() == NULL) { this->lv_kind = kind = VALUE_NULL; } switch (kind) { case VALUE_TEXT: this->lv_sbr = sbr; break; case VALUE_NULL: break; case VALUE_INTEGER: strtonum(this->lv_number.i, sbr.get_data(), sbr.length()); if (scaling != NULL) { scaling->scale(this->lv_number.i); } break; case VALUE_FLOAT: { char scan_value[sbr.length() + 1]; memcpy(scan_value, sbr.get_data(), sbr.length()); scan_value[sbr.length()] = '\0'; this->lv_number.d = strtod(scan_value, NULL); if (scaling != NULL) { scaling->scale(this->lv_number.d); } break; } case VALUE_BOOLEAN: if (strncmp(sbr.get_data(), "true", sbr.length()) == 0 || strncmp(sbr.get_data(), "yes", sbr.length()) == 0) { this->lv_number.i = 1; } else { this->lv_number.i = 0; } break; case VALUE_UNKNOWN: case VALUE__MAX: ensure(0); break; } }; const std::string to_string() const { char buffer[128]; switch (this->lv_kind) { case VALUE_NULL: return "null"; case VALUE_TEXT: return std::string(this->lv_sbr.get_data(), this->lv_sbr.length()); case VALUE_INTEGER: snprintf(buffer, sizeof(buffer), "%" PRId64, this->lv_number.i); break; case VALUE_FLOAT: snprintf(buffer, sizeof(buffer), "%lf", this->lv_number.d); break; case VALUE_BOOLEAN: if (this->lv_number.i) { return "true"; } else { return "false"; } break; case VALUE_UNKNOWN: case VALUE__MAX: ensure(0); break; } return std::string(buffer); }; std::string lv_name; kind_t lv_kind; union value_u { int64_t i; double d; value_u() : i(0) { }; value_u(int64_t i) : i(i) { }; value_u(double d) : d(d) { }; } lv_number; shared_buffer_ref lv_sbr; bool lv_identifier; int lv_column; struct line_range lv_origin; }; struct logline_value_cmp { logline_value_cmp(const std::string *name = NULL, int col = -1) : lvc_name(name), lvc_column(col) { }; bool operator()(const logline_value &lv) { bool retval = true; if (this->lvc_name != NULL) retval = retval && ((*this->lvc_name) == lv.lv_name); if (this->lvc_column != -1) retval = retval && (this->lvc_column == lv.lv_column); return retval; }; const std::string *lvc_name; int lvc_column; }; class log_vtab_impl; /** * Base class for implementations of log format parsers. */ class log_format { public: /** * @return The collection of builtin log formats. */ static std::vector &get_root_formats(void); /** * Template used to register log formats during initialization. */ template class register_root_format { public: register_root_format() { static T format; log_format::lf_root_formats.push_back(&format); }; }; struct action_def { std::string ad_name; std::string ad_label; std::vector ad_cmdline; bool ad_capture_output; action_def() : ad_capture_output(false) { }; bool operator<(const action_def &rhs) const { return this->ad_name < rhs.ad_name; }; }; log_format() : lf_fmt_lock(-1), lf_timestamp_field("timestamp") { }; virtual ~log_format() { }; virtual void clear(void) { this->lf_fmt_lock = -1; this->lf_date_time.clear(); }; /** * Get the name of this log format. * * @return The log format name. */ virtual std::string get_name(void) const = 0; virtual bool match_name(const std::string &filename) { return true; }; /** * Scan a log line to see if it matches this log format. * * @param dst The vector of loglines that the formatter should append to * if it detected a match. * @param offset The offset in the file where this line is located. * @param prefix The contents of the line. * @param len The length of the prefix string. */ virtual bool scan(std::vector &dst, off_t offset, char *prefix, int len) = 0; /** * Remove redundant data from the log line string. * * XXX We should probably also add some attributes to the line here, so we * can highlight things like the date. * * @param line The log line to edit. */ virtual void scrub(std::string &line) { }; virtual void annotate(shared_buffer_ref &sbr, string_attrs_t &sa, std::vector &values) const { }; virtual std::auto_ptr specialized(void) = 0; virtual log_vtab_impl *get_vtab_impl(void) const { return NULL; }; virtual void get_subline(const logline &ll, shared_buffer_ref &sbr) { }; virtual const std::vector *get_actions(const logline_value &lv) const { return NULL; }; virtual const std::set get_source_path() const { std::set retval; retval.insert("default"); return retval; }; void check_for_new_year(std::vector &dst, const struct timeval &log_tv) { if (!dst.empty() && ((dst.back().get_time() - log_tv.tv_sec) > (24 * 60 * 60))) { std::vector::iterator iter; for (iter = dst.begin(); iter != dst.end(); iter++) { time_t ot = iter->get_time(); struct tm *otm; otm = gmtime(&ot); otm->tm_year -= 1; iter->set_time(tm2sec(otm)); } } }; date_time_scanner lf_date_time; int lf_fmt_lock; std::string lf_timestamp_field; int lf_timestamp_field_index; std::map lf_action_defs; protected: static std::vector lf_root_formats; const char *log_scanf(const char *line, const char *fmt[], int expected_matches, const char *time_fmt[], char *time_dest, struct tm *tm_out, struct timeval &tv_out, ...); }; class external_log_format : public log_format { public: struct sample { std::string s_line; logline::level_t s_level; }; struct value_def { value_def() : vd_index(-1), vd_kind(logline_value::VALUE_UNKNOWN), vd_identifier(false), vd_foreign_key(false), vd_unit_field_index(-1), vd_column(-1), vd_hidden(false) { }; std::string vd_name; int vd_index; logline_value::kind_t vd_kind; std::string vd_collate; bool vd_identifier; bool vd_foreign_key; std::string vd_unit_field; int vd_unit_field_index; std::map vd_unit_scaling; int vd_column; bool vd_hidden; std::vector vd_action_list; bool operator<(const value_def &rhs) const { return this->vd_index < rhs.vd_index; }; }; struct pattern { pattern() : p_pcre(NULL) { }; std::string p_string; std::vector p_before_pattern; pcrepp *p_pcre; std::vector p_value_by_index; }; struct level_pattern { level_pattern() : lp_pcre(NULL) { }; std::string lp_regex; pcrepp *lp_pcre; }; external_log_format(const std::string &name) : elf_file_pattern(".*"), elf_filename_pcre(NULL), elf_column_count(0), elf_timestamp_divisor(1.0), elf_body_field("body"), jlf_json(false), jlf_cached_offset(-1), elf_name(name) { this->jlf_line_offsets.reserve(128); }; std::string get_name(void) const { return this->elf_name; }; bool match_name(const std::string &filename) { pcre_context_static<10> pc; pcre_input pi(filename); return this->elf_filename_pcre->match(pc, pi); }; bool scan(std::vector &dst, off_t offset, char *prefix, int len); void annotate(shared_buffer_ref &line, string_attrs_t &sa, std::vector &values) const; void build(std::vector &errors); std::auto_ptr specialized() { external_log_format *elf = new external_log_format(*this); std::auto_ptr retval((log_format *)elf); if (this->jlf_json) { this->jlf_parse_context.reset(new yajlpp_parse_context(this->elf_name)); } else if (this->lf_fmt_lock != -1) { pcrepp *pat = this->elf_pattern_order[this->lf_fmt_lock]->p_pcre; retval->lf_timestamp_field_index = pat->name_index(this->lf_timestamp_field); elf->elf_level_field_index = pat->name_index(elf->elf_level_field); elf->elf_body_field_index = pat->name_index(elf->elf_body_field); } return retval; }; void get_subline(const logline &ll, shared_buffer_ref &sbr); log_vtab_impl *get_vtab_impl(void) const; const std::vector *get_actions(const logline_value &lv) const { std::map::const_iterator iter; const std::vector *retval = NULL; iter = this->elf_value_defs.find(lv.lv_name); if (iter != this->elf_value_defs.end()) { retval = &iter->second.vd_action_list; } return retval; }; const std::set get_source_path() const { return this->elf_source_path; }; std::set elf_source_path; std::string elf_file_pattern; pcrepp *elf_filename_pcre; std::map elf_patterns; std::vector elf_pattern_order; std::vector elf_samples; std::map elf_value_defs; int elf_column_count; double elf_timestamp_divisor; std::string elf_level_field; int elf_level_field_index; std::string elf_body_field; int elf_body_field_index; std::map elf_level_patterns; enum json_log_field { JLF_CONSTANT, JLF_VARIABLE }; struct json_format_element { json_format_element() : jfe_type(JLF_CONSTANT), jfe_default_value("-"), jfe_min_width(0) { }; json_log_field jfe_type; std::string jfe_value; std::string jfe_default_value; int jfe_min_width; }; bool jlf_json; std::vector jlf_line_format; std::vector jlf_line_values; off_t jlf_cached_offset; std::vector jlf_line_offsets; shared_buffer jlf_share_manager; std::string jlf_cached_line; string_attrs_t jlf_line_attrs; std::auto_ptr jlf_parse_context; private: const std::string elf_name; }; #endif lnav-0.7.0/src/log_format_impls.cc000664 000765 000024 00000027316 12311232073 017366 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file log_format_impls.cc */ #include #include "pcrepp.hh" #include "log_format.hh" #include "log_vtab_impl.hh" using namespace std; static pcrepp RDNS_PATTERN("^(?:com|net|org|edu|[a-z][a-z])" "(\\.\\w+)+(.+)"); /** * Attempt to scrub a reverse-DNS string. * * @param str The string to scrub. If the string looks like a reverse-DNS * string, the leading components of the name will be reduced to a single * letter. For example, "com.example.foo" will be reduced to "c.e.foo". * @return The scrubbed version of the input string or the original string * if it is not a reverse-DNS string. */ static string scrub_rdns(const string &str) { pcre_context_static<30> context; pcre_input input(str); string retval; if (RDNS_PATTERN.match(context, input)) { pcre_context::capture_t *cap; cap = context.begin(); for (int index = 0; index < cap->c_begin; index++) { if (index == 0 || str[index - 1] == '.') { if (index > 0) { retval.append(1, '.'); } retval.append(1, str[index]); } } retval += input.get_substr(cap); retval += input.get_substr(cap + 1); } else { retval = str; } return retval; } class generic_log_format : public log_format { static pcrepp &scrub_pattern(void) { static pcrepp SCRUB_PATTERN( "\\d+-(\\d+-\\d+ \\d+:\\d+:\\d+(?:,\\d+)?:)\\w+:(.*)"); return SCRUB_PATTERN; } static const char **get_log_formats() { static const char *log_fmt[] = { "%63[0-9TZ: ,.-]%63[^:]%n", "%63[a-zA-Z0-9:-+/.] [%*x %63[^\n]%n", "%63[a-zA-Z0-9:.,-/] %63[^\n]%n", "%63[a-zA-Z0-9: .,-/] [%*[^]]]%63[^:]%n", "%63[a-zA-Z0-9: .,-/] %63[^\n]%n", "[%63[0-9: .-] %*s %63[^\n]%n", "[%63[a-zA-Z0-9: -+/]] %63[^\n]%n", "[%63[a-zA-Z0-9: -+/]] [%63[a-zA-Z]]%n", "[%63[a-zA-Z0-9: .-+/] %*s %63[^\n]%n", "[%63[a-zA-Z0-9: -+/]] (%*d) %63[^\n]%n", NULL }; return log_fmt; }; struct pcre_format { const char *name; pcrepp pcre; }; static pcre_format *get_pcre_log_formats() { static pcre_format log_fmt[] = { { "", pcrepp("([\\dTZ: ,\\.-]+)([^:]+)") }, { "", pcrepp("([\\w:+/\\.-]+) \\[\\w (.*)") }, { "", pcrepp("([\\w:,/\\.-]+) (.*)") }, { "", pcrepp("([\\w: \\.,/-]+) \\[[^\\]+](.*)") }, { "", pcrepp("([\\w: \\.,/-]+) (.*)") }, { "", pcrepp("\\[([\\d: \\.-]+) \\w+ (.*)") }, { "", pcrepp("\\[([\\w: +/-]+)\\] (.*)") }, { "", pcrepp("\\[([\\w: +/-]+)\\] \\[(\\w+)\\]") }, { "", pcrepp("\\[([\\w: \\.+/-]+)\\] \\w+ (.*)") }, { "", pcrepp("\\[([\\w: +/-]+)\\] \\(\\d+\\) (.*)") }, { NULL, pcrepp("") } }; return log_fmt; }; string get_name() const { return "generic_log"; }; void scrub(string &line) { pcre_context_static<30> context; pcre_input pi(line); string new_line = ""; if (scrub_pattern().match(context, pi)) { pcre_context::capture_t *cap; for (cap = context.begin(); cap != context.end(); cap++) { new_line += scrub_rdns(pi.get_substr(cap)); } line = new_line; } }; bool scan(vector &dst, off_t offset, char *prefix, int len) { bool retval = false; struct tm log_time; char timestr[64 + 32]; struct timeval log_tv; char level[64]; const char *last_pos; int prefix_len; if ((last_pos = this->log_scanf(prefix, get_log_formats(), 2, NULL, timestr, &log_time, log_tv, timestr, level, &prefix_len)) != NULL) { uint16_t millis = 0; if (last_pos[0] == ',' || last_pos[0] == '.') { int subsec_len = 0; sscanf(last_pos + 1, "%hd%n", &millis, &subsec_len); if (millis >= 1000) { millis = 0; } this->lf_date_time.dts_fmt_len += 1 + subsec_len; } this->check_for_new_year(dst, log_tv); dst.push_back(logline(offset, log_tv, logline::string2level(level))); retval = true; } return retval; }; void annotate(shared_buffer_ref &line, string_attrs_t &sa, std::vector &values) const { pcre_format &fmt = get_pcre_log_formats()[this->lf_fmt_lock]; struct line_range lr; int prefix_len = 0; pcre_input pi(line.get_data(), 0, line.length()); pcre_context_static<30> pc; if (!fmt.pcre.match(pc, pi)) { return; } lr.lr_start = pc[0]->c_begin; lr.lr_end = pc[0]->c_end; sa.push_back(string_attr(lr, &logline::L_TIMESTAMP)); const char *level = &line.get_data()[pc[1]->c_begin]; if (logline::string2level(level, pc[1]->length(), true) == logline::LEVEL_UNKNOWN) { prefix_len = pc[0]->c_end; } else { prefix_len = pc[1]->c_end; } lr.lr_start = 0; lr.lr_end = prefix_len; sa.push_back(string_attr(lr, &logline::L_PREFIX)); lr.lr_start = prefix_len; lr.lr_end = line.length(); sa.push_back(string_attr(lr, &textview_curses::SA_BODY)); }; auto_ptr specialized() { auto_ptr retval((log_format *) new generic_log_format(*this)); return retval; }; }; log_format::register_root_format generic_log_instance; class strace_log_format : public log_format { static pcrepp &value_pattern(void) { static pcrepp VALUE_PATTERN( "([0-9:.]*) ([a-zA-Z_][a-zA-Z_0-9]*)\\(" "(.*)\\)" "\\s+= ([-xa-fA-F\\d\\?]+)[^<]+(?:<(\\d+\\.\\d+)>)?"); return VALUE_PATTERN; }; string get_name() const { return "strace_log"; }; bool scan(vector &dst, off_t offset, char *prefix, int len) { static const char *log_fmt[] = { "%63[0-9:].%d", NULL }; static const char *time_fmt[] = { "%H:%M:%S", NULL }; bool retval = false; struct tm log_time; char timestr[64]; struct timeval log_tv; int usecs; if (this->log_scanf(prefix, log_fmt, 2, time_fmt, timestr, &log_time, log_tv, timestr, &usecs)) { logline::level_t level = logline::LEVEL_UNKNOWN; const char * eq; if ((eq = strrchr(prefix, '=')) != NULL) { int rc; if (sscanf(eq, "= %d", &rc) == 1 && rc < 0) { level = logline::LEVEL_ERROR; } } if (!dst.empty() && (log_tv.tv_sec < dst.back().get_time())) { log_tv.tv_sec += (24 * 60 * 60); } log_tv.tv_usec = usecs; dst.push_back(logline(offset, log_tv, level)); retval = true; } return retval; }; auto_ptr specialized() { auto_ptr retval((log_format *) new strace_log_format(*this)); return retval; }; void annotate(shared_buffer_ref &line, string_attrs_t &sa, std::vector &values) const { pcre_context_static<30> pc; pcre_input pi(line.get_data(), 0, line.length()); if (value_pattern().match(pc, pi)) { static struct { const char * name; logline_value::kind_t kind; } columns[] = { { "", logline_value::VALUE_TEXT }, { "funcname", logline_value::VALUE_TEXT }, { "args", logline_value::VALUE_TEXT }, { "result", logline_value::VALUE_TEXT }, { "duration", logline_value::VALUE_FLOAT }, { NULL, logline_value::VALUE_UNKNOWN }, }; pcre_context::iterator iter; struct line_range lr; iter = pc.begin(); if (iter->c_begin != -1) { lr.lr_start = iter->c_begin; lr.lr_end = iter->c_end; sa.push_back(string_attr(lr, &logline::L_TIMESTAMP)); } lr.lr_start = 0; lr.lr_end = line.length(); sa.push_back(string_attr(lr, &logline::L_PREFIX)); lr.lr_start = line.length(); lr.lr_end = line.length(); sa.push_back(string_attr(lr, &textview_curses::SA_BODY)); for (int lpc = 0; columns[lpc].name; lpc++) { pcre_context::iterator cap = pc.begin() + lpc; shared_buffer_ref value_str; if (columns[lpc].name[0] == '\0') { continue; } value_str.subset(line, cap->c_begin, cap->length()); values.push_back(logline_value(columns[lpc].name, columns[lpc].kind, value_str)); } } }; }; log_format::register_root_format strace_log_instance; lnav-0.7.0/src/log_format_loader.cc000664 000765 000024 00000042045 12307601604 017511 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file log_format_loader.cc */ #include "config.h" #include #include #include #include #include #include "yajlpp.hh" #include "lnav_config.hh" #include "log_format.hh" #include "auto_fd.hh" #include "format-text-files.hh" #include "default-log-formats-json.hh" #ifndef SYSCONFDIR #define SYSCONFDIR "/usr/etc" #endif using namespace std; static map LOG_FORMATS; static external_log_format *ensure_format(yajlpp_parse_context *ypc) { const string &name = ypc->get_path_fragment(0); external_log_format *retval; retval = LOG_FORMATS[name]; if (retval == NULL) { LOG_FORMATS[name] = retval = new external_log_format(name); } retval->elf_source_path.insert(ypc->ypc_source.substr(0, ypc->ypc_source.rfind('/'))); return retval; } static int read_format_regex(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { external_log_format *elf = ensure_format(ypc); string regex_name = ypc->get_path_fragment(2); string value = string((const char *)str, len); elf->elf_patterns[regex_name].p_string = value; return 1; } static int read_format_bool(yajlpp_parse_context *ypc, int val) { external_log_format *elf = ensure_format(ypc); string field_name = ypc->get_path_fragment(1); if (field_name == "convert-to-local-time") elf->lf_date_time.dts_local_time = val; else if (field_name == "json") elf->jlf_json = val; return 1; } static int read_format_double(yajlpp_parse_context *ypc, double val) { external_log_format *elf = ensure_format(ypc); string field_name = ypc->get_path_fragment(1); if (field_name == "timestamp-divisor") { if (val <= 0) { fprintf(stderr, "error:%s: timestamp-divisor cannot be less " "than or equal to zero\n", ypc->get_path_fragment(0).c_str()); return 0; } elf->elf_timestamp_divisor = val; } return 1; } static int read_format_int(yajlpp_parse_context *ypc, long long val) { external_log_format *elf = ensure_format(ypc); string field_name = ypc->get_path_fragment(1); if (field_name == "timestamp-divisor") { if (val <= 0) { fprintf(stderr, "error:%s: timestamp-divisor cannot be less " "than or equal to zero\n", ypc->get_path_fragment(0).c_str()); return 0; } elf->elf_timestamp_divisor = val; } return 1; } static int read_format_field(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { external_log_format *elf = ensure_format(ypc); string value = string((const char *)str, len); string field_name = ypc->get_path_fragment(1); if (field_name == "file-pattern") elf->elf_file_pattern = value; else if (field_name == "level-field") elf->elf_level_field = value; else if (field_name == "timestamp-field") elf->lf_timestamp_field = value; else if (field_name == "body-field") elf->elf_body_field = value; return 1; } static int read_levels(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { external_log_format *elf = ensure_format(ypc); string regex = string((const char *)str, len); logline::level_t level = logline::string2level(ypc->get_path_fragment(2).c_str()); elf->elf_level_patterns[level].lp_regex = regex; return 1; } static int read_value_def(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { external_log_format *elf = ensure_format(ypc); string value_name = ypc->get_path_fragment(2); string field_name = ypc->get_path_fragment(3); string val = string((const char *)str, len); elf->elf_value_defs[value_name].vd_name = value_name; if (field_name == "kind") { logline_value::kind_t kind; if ((kind = logline_value::string2kind(val.c_str())) == logline_value::VALUE_UNKNOWN) { fprintf(stderr, "unknown value kind %s\n", val.c_str()); return 0; } elf->elf_value_defs[value_name].vd_kind = kind; } else if (field_name == "unit" && ypc->get_path_fragment(4) == "field") { elf->elf_value_defs[value_name].vd_unit_field = val; } else if (field_name == "collate") { elf->elf_value_defs[value_name].vd_collate = val; } return 1; } static int read_value_action(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { external_log_format *elf = ensure_format(ypc); string value_name = ypc->get_path_fragment(2); string field_name = ypc->get_path_fragment(3); string val = string((const char *)str, len); elf->elf_value_defs[value_name].vd_action_list.push_back(val); return 1; } static int read_value_bool(yajlpp_parse_context *ypc, int val) { external_log_format *elf = ensure_format(ypc); string value_name = ypc->get_path_fragment(2); string key_name = ypc->get_path_fragment(3); if (key_name == "identifier") elf->elf_value_defs[value_name].vd_identifier = val; else if (key_name == "foreign-key") elf->elf_value_defs[value_name].vd_foreign_key = val; else if (key_name == "hidden") elf->elf_value_defs[value_name].vd_hidden = val; return 1; } static int read_action_def(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { external_log_format *elf = ensure_format(ypc); string action_name = ypc->get_path_fragment(2); string field_name = ypc->get_path_fragment(3); string val = string((const char *)str, len); elf->lf_action_defs[action_name].ad_name = action_name; if (field_name == "label") elf->lf_action_defs[action_name].ad_label = val; return 1; } static int read_action_bool(yajlpp_parse_context *ypc, int val) { external_log_format *elf = ensure_format(ypc); string action_name = ypc->get_path_fragment(2); string field_name = ypc->get_path_fragment(3); elf->lf_action_defs[action_name].ad_capture_output = val; return 1; } static int read_action_cmd(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { external_log_format *elf = ensure_format(ypc); string action_name = ypc->get_path_fragment(2); string field_name = ypc->get_path_fragment(3); string val = string((const char *)str, len); elf->lf_action_defs[action_name].ad_name = action_name; elf->lf_action_defs[action_name].ad_cmdline.push_back(val); return 1; } static external_log_format::sample &ensure_sample(external_log_format *elf, int index) { elf->elf_samples.resize(index + 1); return elf->elf_samples[index]; } static int read_scaling(yajlpp_parse_context *ypc, double val) { external_log_format *elf = ensure_format(ypc); string value_name = ypc->get_path_fragment(2); string scale_name = ypc->get_path_fragment(5); if (scale_name.empty()) { fprintf(stderr, "error:%s:%s: scaling factor field cannot be empty\n", ypc->get_path_fragment(0).c_str(), value_name.c_str()); return 0; } struct scaling_factor &sf = elf->elf_value_defs[value_name].vd_unit_scaling[scale_name.substr(1)]; if (scale_name[0] == '/') { sf.sf_op = SO_DIVIDE; } else if (scale_name[0] == '*') { sf.sf_op = SO_MULTIPLY; } else { fprintf(stderr, "error:%s:%s: scaling factor field must start with '/' or '*'\n", ypc->get_path_fragment(0).c_str(), value_name.c_str()); return 0; } sf.sf_value = val; return 1; } static int read_sample_line(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { external_log_format *elf = ensure_format(ypc); string val = string((const char *)str, len); int index = ypc->ypc_array_index.back(); external_log_format::sample &sample = ensure_sample(elf, index); sample.s_line = val; return 1; } static external_log_format::json_format_element & ensure_json_format_element(external_log_format *elf, int index) { elf->jlf_line_format.resize(index + 1); return elf->jlf_line_format[index]; } static int read_json_constant(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { external_log_format *elf = ensure_format(ypc); string val = string((const char *)str, len); ypc->ypc_array_index.back() += 1; int index = ypc->ypc_array_index.back(); external_log_format::json_format_element &jfe = ensure_json_format_element(elf, index); jfe.jfe_type = external_log_format::JLF_CONSTANT; jfe.jfe_default_value = val; return 1; } static int read_json_variable(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { external_log_format *elf = ensure_format(ypc); string val = string((const char *)str, len); int index = ypc->ypc_array_index.back(); external_log_format::json_format_element &jfe = ensure_json_format_element(elf, index); string field_name = ypc->get_path_fragment(3); jfe.jfe_type = external_log_format::JLF_VARIABLE; if (field_name == "field") jfe.jfe_value = val; else if (field_name == "default-value") jfe.jfe_default_value = val; return 1; } static int read_json_variable_num(yajlpp_parse_context *ypc, long long val) { external_log_format *elf = ensure_format(ypc); int index = ypc->ypc_array_index.back(); external_log_format::json_format_element &jfe = ensure_json_format_element(elf, index); string field_name = ypc->get_path_fragment(2); jfe.jfe_type = external_log_format::JLF_VARIABLE; jfe.jfe_min_width = val; return 1; } static struct json_path_handler format_handlers[] = { json_path_handler("^/\\w+/regex/[^/]+/pattern$", read_format_regex), json_path_handler("^/\\w+/(json|convert-to-local-time)$", read_format_bool), json_path_handler("^/\\w+/timestamp-divisor$", read_format_double) .add_cb(read_format_int), json_path_handler("^/\\w+/(file-pattern|level-field|timestamp-field|body-field|url|title|description)$", read_format_field), json_path_handler("^/\\w+/level/" "(trace|debug|info|warning|error|critical|fatal)$", read_levels), json_path_handler("^/\\w+/value/\\w+/(kind|collate|unit/field)$", read_value_def), json_path_handler("^/\\w+/value/\\w+/(identifier|foreign-key|hidden)$", read_value_bool), json_path_handler("^/\\w+/value/\\w+/unit/scaling-factor/.*$", read_scaling), json_path_handler("^/\\w+/value/\\w+/action-list#", read_value_action), json_path_handler("^/\\w+/action/\\w+/label", read_action_def), json_path_handler("^/\\w+/action/\\w+/capture-output", read_action_bool), json_path_handler("^/\\w+/action/\\w+/cmd#", read_action_cmd), json_path_handler("^/\\w+/sample#/line$", read_sample_line), json_path_handler("^/\\w+/line-format#/(field|default-value)$", read_json_variable), json_path_handler("^/\\w+/line-format#/min-width$", read_json_variable_num), json_path_handler("^/\\w+/line-format#$", read_json_constant), json_path_handler() }; static void write_sample_file(void) { string sample_path = dotlnav_path("formats/default/default-formats.json.sample"); auto_fd sample_fd; if ((sample_fd = open(sample_path.c_str(), O_WRONLY|O_TRUNC|O_CREAT, 0644)) == -1) { perror("error: unable to write default format file"); } else { write(sample_fd.get(), default_log_formats_json, strlen(default_log_formats_json)); } string sh_path = dotlnav_path("formats/default/dump-pid.sh"); auto_fd sh_fd; if ((sh_fd = open(sh_path.c_str(), O_WRONLY|O_TRUNC|O_CREAT, 0755)) == -1) { perror("error: unable to write default text file"); } else { write(sh_fd.get(), dump_pid_sh, strlen(dump_pid_sh)); } } static void load_from_path(const string &path, std::vector &errors) { string format_path = path + "/formats/*/*.json"; static_root_mem gl; yajl_handle handle; log_info("loading formats from path: %s", format_path.c_str()); if (glob(format_path.c_str(), 0, NULL, gl.inout()) == 0) { for (int lpc = 0; lpc < (int)gl->gl_pathc; lpc++) { string filename(gl->gl_pathv[lpc]); auto_fd fd; log_info("loading formats from file: %s", filename.c_str()); yajlpp_parse_context ypc(filename, format_handlers); if ((fd = open(gl->gl_pathv[lpc], O_RDONLY)) == -1) { char errmsg[1024]; snprintf(errmsg, sizeof(errmsg), "error: unable to open format file -- %s", gl->gl_pathv[lpc]); perror(errmsg); } else { char buffer[2048]; int rc = -1; handle = yajl_alloc(&ypc.ypc_callbacks, NULL, &ypc); while (true) { rc = read(fd, buffer, sizeof(buffer)); if (rc == 0) { break; } else if (rc == -1) { errors.push_back(filename + ":unable to read file -- " + string(strerror(errno))); break; } if (yajl_parse(handle, (const unsigned char *)buffer, rc) != yajl_status_ok) { errors.push_back(filename + ": invalid json -- " + string((char *)yajl_get_error(handle, 1, (unsigned char *)buffer, rc))); break; } } if (rc == 0) { if (yajl_complete_parse(handle) != yajl_status_ok) { errors.push_back(filename + ": invalid json -- " + string((char *)yajl_get_error(handle, 0, NULL, 0))); } } yajl_free(handle); } } } } void load_formats(const std::vector &extra_paths, std::vector &errors) { string default_source = string(dotlnav_path("formats") + "/default/"); yajlpp_parse_context ypc_builtin(default_source, format_handlers); std::vector retval; yajl_handle handle; write_sample_file(); handle = yajl_alloc(&ypc_builtin.ypc_callbacks, NULL, &ypc_builtin); if (yajl_parse(handle, (const unsigned char *)default_log_formats_json, strlen(default_log_formats_json)) != yajl_status_ok) { errors.push_back("builtin: invalid json -- " + string((char *)yajl_get_error(handle, 1, (unsigned char *)default_log_formats_json, strlen(default_log_formats_json)))); } yajl_complete_parse(handle); yajl_free(handle); load_from_path("/etc/lnav", errors); load_from_path(SYSCONFDIR "/lnav", errors); load_from_path(dotlnav_path(""), errors); for (vector::const_iterator path_iter = extra_paths.begin(); path_iter != extra_paths.end(); ++path_iter) { load_from_path(*path_iter, errors); } for (map::iterator iter = LOG_FORMATS.begin(); iter != LOG_FORMATS.end(); ++iter) { iter->second->build(errors); if (errors.empty()) { log_format::get_root_formats().insert(log_format::get_root_formats().begin(), iter->second); } } } lnav-0.7.0/src/log_format_loader.hh000664 000765 000024 00000003404 12305014302 017506 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file log_format_loader.hh */ #ifndef __log_format_loader_hh #define __log_format_loader_hh #include #include void load_formats(const std::vector &extra_paths, std::vector &errors); #endif lnav-0.7.0/src/log_vtab_impl.cc000664 000765 000024 00000051227 12307624343 016657 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "lnav_log.hh" #include "sql_util.hh" #include "log_vtab_impl.hh" #include "logfile_sub_source.hh" using namespace std; static struct log_cursor log_cursor_latest; static sql_progress_callback_t vtab_progress_callback; static const char *type_to_string(int type) { switch (type) { case SQLITE_FLOAT: return "float"; case SQLITE_INTEGER: return "integer"; case SQLITE_TEXT: return "text"; } ensure("Invalid sqlite type"); return NULL; } std::string log_vtab_impl::get_table_statement(void) { std::vector cols; std::vector::const_iterator iter; std::ostringstream oss; oss << "CREATE TABLE " << this->get_name() << " (\n" << " log_line integer PRIMARY KEY,\n" << " log_part text collate naturalnocase,\n" << " log_time datetime,\n" << " log_idle_msecs int,\n" << " log_level text collate loglevel,\n" << " log_mark boolean,\n"; this->get_columns(cols); this->vi_column_count = cols.size(); for (iter = cols.begin(); iter != cols.end(); iter++) { auto_mem coldecl; require(iter->vc_name != NULL); coldecl = sqlite3_mprintf(" %Q %s %s collate %Q,\n", iter->vc_name, type_to_string(iter->vc_type), iter->vc_hidden ? "hidden" : "", (iter->vc_collator == NULL || iter->vc_collator[0] == '\0') ? "BINARY" : iter->vc_collator); oss << coldecl; } oss << " log_path text hidden collate naturalnocase,\n" << " log_text text hidden\n" << ");\n"; return oss.str(); } struct vtab { sqlite3_vtab base; sqlite3 * db; textview_curses *tc; logfile_sub_source *lss; log_vtab_impl * vi; }; struct vtab_cursor { sqlite3_vtab_cursor base; struct log_cursor log_cursor; shared_buffer_ref log_msg; std::vector line_values; }; static int vt_destructor(sqlite3_vtab *p_svt); static int vt_create(sqlite3 *db, void *pAux, int argc, const char *const *argv, sqlite3_vtab **pp_vt, char **pzErr) { log_vtab_manager *vm = (log_vtab_manager *)pAux; int rc = SQLITE_OK; vtab *p_vt; /* Allocate the sqlite3_vtab/vtab structure itself */ p_vt = (vtab *)sqlite3_malloc(sizeof(*p_vt)); if (p_vt == NULL) { return SQLITE_NOMEM; } memset(&p_vt->base, 0, sizeof(sqlite3_vtab)); p_vt->db = db; /* Declare the vtable's structure */ p_vt->vi = vm->lookup_impl(argv[3]); if (p_vt->vi == NULL) { return SQLITE_ERROR; } p_vt->tc = vm->get_view(); p_vt->lss = vm->get_source(); rc = sqlite3_declare_vtab(db, p_vt->vi->get_table_statement().c_str()); /* Success. Set *pp_vt and return */ *pp_vt = &p_vt->base; return rc; } static int vt_destructor(sqlite3_vtab *p_svt) { vtab *p_vt = (vtab *)p_svt; /* Free the SQLite structure */ sqlite3_free(p_vt); return SQLITE_OK; } static int vt_connect(sqlite3 *db, void *p_aux, int argc, const char *const *argv, sqlite3_vtab **pp_vt, char **pzErr) { return vt_create(db, p_aux, argc, argv, pp_vt, pzErr); } static int vt_disconnect(sqlite3_vtab *pVtab) { return vt_destructor(pVtab); } static int vt_destroy(sqlite3_vtab *p_vt) { return vt_destructor(p_vt); } static int vt_next(sqlite3_vtab_cursor *cur); static int vt_open(sqlite3_vtab *p_svt, sqlite3_vtab_cursor **pp_cursor) { vtab *p_vt = (vtab *)p_svt; p_vt->base.zErrMsg = NULL; vtab_cursor *p_cur = (vtab_cursor *)new vtab_cursor(); *pp_cursor = (sqlite3_vtab_cursor *)p_cur; p_cur->base.pVtab = p_svt; p_cur->log_cursor.lc_curr_line = vis_line_t(-1); p_cur->log_cursor.lc_end_line = vis_line_t(p_vt->lss->text_line_count()); p_cur->log_cursor.lc_sub_index = 0; vt_next((sqlite3_vtab_cursor *)p_cur); return p_cur ? SQLITE_OK : SQLITE_NOMEM; } static int vt_close(sqlite3_vtab_cursor *cur) { vtab_cursor *p_cur = (vtab_cursor *)cur; /* Free cursor struct. */ delete p_cur; return SQLITE_OK; } static int vt_eof(sqlite3_vtab_cursor *cur) { vtab_cursor *vc = (vtab_cursor *)cur; return vc->log_cursor.is_eof(); } static int vt_next(sqlite3_vtab_cursor *cur) { vtab_cursor *vc = (vtab_cursor *)cur; vtab * vt = (vtab *)cur->pVtab; bool done = false; vc->line_values.clear(); do { log_cursor_latest = vc->log_cursor; if (((log_cursor_latest.lc_curr_line % 1024) == 0) && vtab_progress_callback(log_cursor_latest)) { break; } done = vt->vi->next(vc->log_cursor, *vt->lss); } while (!done); return SQLITE_OK; } static int vt_column(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int col) { vtab_cursor *vc = (vtab_cursor *)cur; vtab * vt = (vtab *)cur->pVtab; content_line_t cl(vt->lss->at(vc->log_cursor.lc_curr_line)); logfile * lf = vt->lss->find(cl); logfile::iterator ll = lf->begin() + cl; require(col >= 0); /* Just return the ordinal of the column requested. */ switch (col) { case VT_COL_LINE_NUMBER: { sqlite3_result_int64(ctx, vc->log_cursor.lc_curr_line); } break; case VT_COL_PARTITION: { vis_bookmarks &vb = vt->tc->get_bookmarks(); bookmark_vector &bv = vb[&textview_curses::BM_PARTITION]; bookmark_vector::iterator iter; vis_line_t prev_line; char part_name[64]; int index; prev_line = vis_line_t(vc->log_cursor.lc_curr_line); ++prev_line; iter = lower_bound(bv.begin(), bv.end(), prev_line); index = distance(bv.begin(), iter); snprintf(part_name, sizeof(part_name), "p.%d", index); if (iter == bv.begin()) { sqlite3_result_text(ctx, part_name, strlen(part_name), SQLITE_TRANSIENT); } else { --iter; content_line_t part_line = vt->lss->at(*iter); std::map &bm_meta = vt->lss->get_user_bookmark_metadata(); std::map::iterator meta_iter; meta_iter = bm_meta.find(part_line); if (meta_iter != bm_meta.end()) { sqlite3_result_text(ctx, meta_iter->second.bm_name.c_str(), meta_iter->second.bm_name.size(), SQLITE_TRANSIENT); } else { sqlite3_result_text(ctx, part_name, strlen(part_name), SQLITE_TRANSIENT); } } } break; case VT_COL_LOG_TIME: { char buffer[64]; sql_strftime(buffer, sizeof(buffer), ll->get_time(), ll->get_millis()); sqlite3_result_text(ctx, buffer, strlen(buffer), SQLITE_TRANSIENT); } break; case VT_COL_IDLE_MSECS: if (vc->log_cursor.lc_curr_line == 0) { sqlite3_result_int64(ctx, 0); } else { content_line_t prev_cl(vt->lss->at(vis_line_t( vc->log_cursor.lc_curr_line - 1))); logfile * prev_lf = vt->lss->find(prev_cl); logfile::iterator prev_ll = prev_lf->begin() + prev_cl; uint64_t prev_time, curr_line_time; prev_time = prev_ll->get_time() * 1000ULL; prev_time += prev_ll->get_millis(); curr_line_time = ll->get_time() * 1000ULL; curr_line_time += ll->get_millis(); // require(curr_line_time >= prev_time); sqlite3_result_int64(ctx, curr_line_time - prev_time); } break; case VT_COL_LEVEL: { const char *level_name = ll->get_level_name(); sqlite3_result_text(ctx, level_name, strlen(level_name), SQLITE_STATIC); } break; case VT_COL_MARK: { sqlite3_result_int(ctx, ll->is_marked()); } break; default: if (col > (VT_COL_MAX + vt->vi->vi_column_count - 1)) { int post_col_number = col - (VT_COL_MAX + vt->vi->vi_column_count - 1) - 1; if (post_col_number == 0) { const string &fn = lf->get_filename(); sqlite3_result_text(ctx, fn.c_str(), fn.length(), SQLITE_STATIC); } else { shared_buffer_ref line; if (lf->read_line(ll, line)) { sqlite3_result_text(ctx, line.get_data(), line.length(), SQLITE_TRANSIENT); } } } else { if (vc->line_values.empty()) { logfile::iterator line_iter; line_iter = lf->begin() + cl; lf->read_line(line_iter, vc->log_msg); vt->vi->extract(lf, vc->log_msg, vc->line_values); } size_t sub_col = col - VT_COL_MAX; std::vector::iterator lv_iter; lv_iter = find_if(vc->line_values.begin(), vc->line_values.end(), logline_value_cmp(NULL, sub_col)); if (lv_iter != vc->line_values.end()) { switch (lv_iter->lv_kind) { case logline_value::VALUE_NULL: sqlite3_result_null(ctx); break; case logline_value::VALUE_TEXT: { const char *text_value = lv_iter->lv_sbr.get_data(); sqlite3_result_text(ctx, text_value, lv_iter->lv_sbr.length(), SQLITE_TRANSIENT); break; } case logline_value::VALUE_BOOLEAN: case logline_value::VALUE_INTEGER: sqlite3_result_int64(ctx, lv_iter->lv_number.i); break; case logline_value::VALUE_FLOAT: sqlite3_result_double(ctx, lv_iter->lv_number.d); break; case logline_value::VALUE_UNKNOWN: case logline_value::VALUE__MAX: require(0); break; } } else { sqlite3_result_null(ctx); } } break; } return SQLITE_OK; } static int vt_rowid(sqlite3_vtab_cursor *cur, sqlite_int64 *p_rowid) { vtab_cursor *p_cur = (vtab_cursor *)cur; *p_rowid = (((uint64_t)p_cur->log_cursor.lc_curr_line) << 8) | (p_cur->log_cursor.lc_sub_index & 0xff); return SQLITE_OK; } void log_cursor::update(unsigned char op, vis_line_t vl, bool exact) { switch (op) { case SQLITE_INDEX_CONSTRAINT_EQ: this->lc_curr_line = vl; this->lc_end_line = vis_line_t(this->lc_curr_line + 1); break; case SQLITE_INDEX_CONSTRAINT_GE: this->lc_curr_line = vl; break; case SQLITE_INDEX_CONSTRAINT_GT: this->lc_curr_line = vis_line_t(vl + (exact ? 1 : 0)); break; case SQLITE_INDEX_CONSTRAINT_LE: this->lc_end_line = vis_line_t(vl + (exact ? 1 : 0)); break; case SQLITE_INDEX_CONSTRAINT_LT: this->lc_end_line = vl; break; } } static int vt_filter(sqlite3_vtab_cursor *p_vtc, int idxNum, const char *idxStr, int argc, sqlite3_value **argv) { vtab_cursor *p_cur = (vtab_cursor *)p_vtc; vtab * vt = (vtab *)p_vtc->pVtab; sqlite3_index_info::sqlite3_index_constraint *index = ( sqlite3_index_info::sqlite3_index_constraint *)idxStr; log_info("filter called: %d", idxNum); if (!idxNum) { return SQLITE_OK; } p_cur->log_cursor.lc_curr_line = vis_line_t(0); p_cur->log_cursor.lc_end_line = vis_line_t(vt->lss->text_line_count()); for (int lpc = 0; lpc < idxNum; lpc++) { switch (index[lpc].iColumn) { case VT_COL_LINE_NUMBER: p_cur->log_cursor.update(index[lpc].op, vis_line_t(sqlite3_value_int64(argv[lpc]))); break; case VT_COL_LOG_TIME: { const unsigned char *datestr = sqlite3_value_text(argv[lpc]); date_time_scanner dts; struct timeval tv; struct tm mytm; vis_line_t vl; dts.scan((const char *)datestr, NULL, &mytm, tv); if ((vl = vt->lss->find_from_time(tv)) == -1) { p_cur->log_cursor.lc_curr_line = p_cur->log_cursor.lc_end_line; } else { p_cur->log_cursor.update(index[lpc].op, vl, false); } break; } } } return SQLITE_OK; } static int vt_best_index(sqlite3_vtab *tab, sqlite3_index_info *p_info) { std::vector indexes; int argvInUse = 0; log_info("best index called: nConstraint=%d", p_info->nConstraint); for (int lpc = 0; lpc < p_info->nConstraint; lpc++) { if (!p_info->aConstraint[lpc].usable || p_info->aConstraint[lpc].op == SQLITE_INDEX_CONSTRAINT_MATCH) { continue; } switch (p_info->aConstraint[lpc].iColumn) { case VT_COL_LINE_NUMBER: argvInUse += 1; indexes.push_back(p_info->aConstraint[lpc]); p_info->aConstraintUsage[lpc].argvIndex = argvInUse; break; } } if (!argvInUse) { for (int lpc = 0; lpc < p_info->nConstraint; lpc++) { if (!p_info->aConstraint[lpc].usable || p_info->aConstraint[lpc].op == SQLITE_INDEX_CONSTRAINT_MATCH) { continue; } switch (p_info->aConstraint[lpc].iColumn) { case VT_COL_LOG_TIME: argvInUse += 1; indexes.push_back(p_info->aConstraint[lpc]); p_info->aConstraintUsage[lpc].argvIndex = argvInUse; break; } } } if (argvInUse) { sqlite3_index_info::sqlite3_index_constraint *index_copy; size_t len = indexes.size() * sizeof(*index_copy); log_info("found index, passing %d args", argvInUse); index_copy = (sqlite3_index_info::sqlite3_index_constraint *) sqlite3_malloc(len); if (!index_copy) { return SQLITE_NOMEM; } memcpy(index_copy, &indexes[0], len); p_info->idxNum = argvInUse; p_info->idxStr = (char *) index_copy; p_info->needToFreeIdxStr = 1; p_info->estimatedCost = 1.0; } return SQLITE_OK; } static int vt_update(sqlite3_vtab *tab, int argc, sqlite3_value **argv, sqlite_int64 *rowid) { vtab *vt = (vtab *)tab; int retval = SQLITE_READONLY; if (argc > 1 && sqlite3_value_type(argv[0]) != SQLITE_NULL && sqlite3_value_int64(argv[0]) == sqlite3_value_int64(argv[1])) { int64_t rowid = sqlite3_value_int64(argv[0]) >> 8; int val = sqlite3_value_int(argv[2 + VT_COL_MARK]); vt->tc->set_user_mark(&textview_curses::BM_USER, vis_line_t(rowid), val); retval = SQLITE_OK; } return retval; } static sqlite3_module vtab_module = { 0, /* iVersion */ vt_create, /* xCreate - create a vtable */ vt_connect, /* xConnect - associate a vtable with a connection */ vt_best_index, /* xBestIndex - best index */ vt_disconnect, /* xDisconnect - disassociate a vtable with a connection */ vt_destroy, /* xDestroy - destroy a vtable */ vt_open, /* xOpen - open a cursor */ vt_close, /* xClose - close a cursor */ vt_filter, /* xFilter - configure scan constraints */ vt_next, /* xNext - advance a cursor */ vt_eof, /* xEof - inidicate end of result set*/ vt_column, /* xColumn - read data */ vt_rowid, /* xRowid - read data */ vt_update, /* xUpdate - write data */ NULL, /* xBegin - begin transaction */ NULL, /* xSync - sync transaction */ NULL, /* xCommit - commit transaction */ NULL, /* xRollback - rollback transaction */ NULL, /* xFindFunction - function overloading */ }; static int progress_callback(void *ptr) { int retval = 0; if (vtab_progress_callback != NULL) { retval = vtab_progress_callback(log_cursor_latest); } return retval; } log_vtab_manager::log_vtab_manager(sqlite3 *memdb, textview_curses &tc, logfile_sub_source &lss, sql_progress_callback_t pc) : vm_db(memdb), vm_textview(tc), vm_source(lss) { sqlite3_create_module(this->vm_db, "log_vtab_impl", &vtab_module, this); vtab_progress_callback = pc; sqlite3_progress_handler(memdb, 32, progress_callback, NULL); } string log_vtab_manager::register_vtab(log_vtab_impl *vi) { string retval; if (this->vm_impls.find(vi->get_name()) == this->vm_impls.end()) { auto_mem errmsg(sqlite3_free); char * sql; int rc; this->vm_impls[vi->get_name()] = vi; sql = sqlite3_mprintf("CREATE VIRTUAL TABLE %s " "USING log_vtab_impl(%s)", vi->get_name().c_str(), vi->get_name().c_str()); rc = sqlite3_exec(this->vm_db, sql, NULL, NULL, errmsg.out()); if (rc != SQLITE_OK) { retval = errmsg; } sqlite3_free(sql); } else { retval = "a table with the given name already exists"; } return retval; } string log_vtab_manager::unregister_vtab(std::string name) { string retval = ""; if (this->vm_impls.find(name) == this->vm_impls.end()) { retval = "unknown log line table -- " + name; } else { char *sql; int rc; sql = sqlite3_mprintf("DROP TABLE %s ", name.c_str()); rc = sqlite3_exec(this->vm_db, sql, NULL, NULL, NULL); require(rc == SQLITE_OK); sqlite3_free(sql); this->vm_impls.erase(name); } return retval; } lnav-0.7.0/src/log_vtab_impl.hh000664 000765 000024 00000012276 12307623342 016670 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __vtab_impl_hh #define __vtab_impl_hh #include #include #include #include #include "textview_curses.hh" #include "logfile_sub_source.hh" enum { VT_COL_LINE_NUMBER, VT_COL_PARTITION, VT_COL_LOG_TIME, VT_COL_IDLE_MSECS, VT_COL_LEVEL, VT_COL_MARK, VT_COL_MAX }; class logfile_sub_source; struct log_cursor { vis_line_t lc_curr_line; int lc_sub_index; vis_line_t lc_end_line; void update(unsigned char op, vis_line_t vl, bool exact = true); void set_eof() { this->lc_curr_line = this->lc_end_line = vis_line_t(0); }; bool is_eof() const { return this->lc_curr_line == this->lc_end_line; }; }; class log_vtab_impl { public: struct vtab_column { vtab_column(const char *name = NULL, int type = SQLITE3_TEXT, const char *collator = NULL, bool hidden = false) : vc_name(name), vc_type(type), vc_collator(collator), vc_hidden(hidden) { }; const char *vc_name; int vc_type; const char *vc_collator; bool vc_hidden; }; log_vtab_impl(const std::string name) : vi_name(name) { this->vi_attrs.resize(128); }; virtual ~log_vtab_impl() { }; const std::string &get_name(void) const { return this->vi_name; }; std::string get_table_statement(void); virtual bool next(log_cursor &lc, logfile_sub_source &lss) { lc.lc_curr_line = lc.lc_curr_line + vis_line_t(1); lc.lc_sub_index = 0; if (lc.is_eof()) { return true; } content_line_t cl(lss.at(lc.lc_curr_line)); logfile * lf = lss.find(cl); logfile::iterator lf_iter = lf->begin() + cl; if (lf_iter->get_level() & logline::LEVEL_CONTINUED) { return false; } log_format *format = lf->get_format(); if (format != NULL && format->get_name() == this->vi_name) { return true; } return false; }; virtual void get_columns(std::vector &cols) { }; virtual void get_foreign_keys(std::vector &keys_inout) { keys_inout.push_back("log_line"); keys_inout.push_back("log_mark"); }; virtual void extract(logfile *lf, shared_buffer_ref &line, std::vector &values) { log_format * format = lf->get_format(); this->vi_attrs.clear(); format->annotate(line, this->vi_attrs, values); }; int vi_column_count; private: string_attrs_t vi_attrs; const std::string vi_name; }; typedef int (*sql_progress_callback_t)(const log_cursor &lc); class log_vtab_manager { public: typedef std::map::const_iterator iterator; log_vtab_manager(sqlite3 *db, textview_curses &tc, logfile_sub_source &lss, sql_progress_callback_t); textview_curses *get_view() const { return &this->vm_textview; }; logfile_sub_source *get_source() { return &this->vm_source; }; std::string register_vtab(log_vtab_impl *vi); std::string unregister_vtab(std::string name); log_vtab_impl *lookup_impl(std::string name) { return this->vm_impls[name]; }; iterator begin() const { return this->vm_impls.begin(); }; iterator end() const { return this->vm_impls.end(); }; private: sqlite3 * vm_db; textview_curses &vm_textview; logfile_sub_source &vm_source; std::map vm_impls; }; #endif lnav-0.7.0/src/logfile.cc000664 000765 000024 00000031650 12311357744 015463 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file logfile.cc */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include "logfile.hh" #include "lnav_util.hh" using namespace std; static const size_t MAX_UNRECOGNIZED_LINES = 1000; logfile::logfile(string filename, auto_fd fd) throw (error) : lf_filename(filename), lf_index_time(0), lf_index_size(0), lf_is_closed(false) { int reserve_size = 100; require(filename.size() > 0); this->lf_time_offset.tv_sec = 0; this->lf_time_offset.tv_usec = 0; memset(&this->lf_stat, 0, sizeof(this->lf_stat)); if (fd == -1) { char resolved_path[PATH_MAX]; errno = 0; if (realpath(filename.c_str(), resolved_path) == NULL) { throw error(resolved_path, errno); } filename = resolved_path; if (stat(filename.c_str(), &this->lf_stat) == -1) { throw error(filename, errno); } reserve_size = this->lf_stat.st_size / 100; if (!S_ISREG(this->lf_stat.st_mode)) { throw error(filename, EINVAL); } if ((fd = open(filename.c_str(), O_RDONLY)) == -1) { throw error(filename, errno); } if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { throw error(filename, errno); } this->lf_valid_filename = true; } else { fstat(fd, &this->lf_stat); this->lf_valid_filename = false; } this->lf_content_id = hash_string(this->lf_filename); this->lf_line_buffer.set_fd(fd); this->lf_index.reserve(reserve_size); ensure(this->invariant()); } logfile::~logfile() { } bool logfile::exists(void) const { struct stat st; if (!this->lf_valid_filename) { return true; } if (::stat(this->lf_filename.c_str(), &st) == -1) { return false; } return this->lf_stat.st_dev == st.st_dev && this->lf_stat.st_ino == st.st_ino; } void logfile::process_prefix(off_t offset, char *prefix, int len) { bool found = false; if (this->lf_format.get() != NULL) { /* We've locked onto a format, just use that scanner. */ found = this->lf_format->scan(this->lf_index, offset, prefix, len); } else if (this->lf_index.size() < MAX_UNRECOGNIZED_LINES) { vector &root_formats = log_format::get_root_formats(); vector::iterator iter; /* * Try each scanner until we get a match. Fortunately, all the formats * are sufficiently different that there are no ambiguities... */ for (iter = root_formats.begin(); iter != root_formats.end() && !found; ++iter) { if (!(*iter)->match_name(this->lf_filename)) continue; (*iter)->clear(); (*iter)->lf_date_time.set_base_time(this->lf_line_buffer.get_file_time()); if ((*iter)->lf_date_time.dts_base_time == 0) { (*iter)->lf_date_time.set_base_time(this->lf_stat.st_mtime); } if ((*iter)->scan(this->lf_index, offset, prefix, len)) { #if 0 require(this->lf_index.size() == 1 || (this->lf_index[this->lf_index.size() - 2] < this->lf_index[this->lf_index.size() - 1])); #endif this->lf_format = auto_ptr((*iter)->specialized()); this->lf_content_id = hash_string(string(prefix, len)); found = true; /* * We'll go ahead and assume that any previous lines were * written out at the same time as the last one, so we need to * go back and update everything. */ logline &last_line = this->lf_index[this->lf_index.size() - 1]; for (size_t lpc = 0; lpc < this->lf_index.size() - 1; lpc++) { this->lf_index[lpc].set_time(last_line.get_time()); this->lf_index[lpc].set_millis(last_line.get_millis()); } } } } if (found) { if (this->lf_index.size() >= 2) { logline &second_to_last = this->lf_index[this->lf_index.size() - 2]; logline &latest = this->lf_index.back(); if (latest < second_to_last) { latest.set_time(second_to_last.get_time()); latest.set_millis(second_to_last.get_millis()); } } } /* If the scanner didn't match, than we need to add it. */ if (!found) { logline::level_t last_level = logline::LEVEL_UNKNOWN; time_t last_time = this->lf_index_time; short last_millis = 0; if (!this->lf_index.empty()) { logline &ll = this->lf_index.back(); /* * Assume this line is part of the previous one(s) and copy the * metadata over. */ last_time = ll.get_time(); last_millis = ll.get_millis(); if (this->lf_format.get() != NULL) { last_level = (logline::level_t) (ll.get_level() | logline::LEVEL_CONTINUED); } } this->lf_index.push_back(logline(offset, last_time, last_millis, last_level)); } } bool logfile::rebuild_index(logfile_observer *lo) throw (line_buffer::error, logfile::error) { bool retval = false; struct stat st; if (fstat(this->lf_line_buffer.get_fd(), &st) == -1) { throw error(this->lf_filename, errno); } /* Check for new data based on the file size. */ if (this->lf_index_size < st.st_size) { off_t last_off, off; line_value lv; if (!this->lf_index.empty()) { off = this->lf_index.back().get_offset(); /* * Drop the last line we read since it might have been a partial * read. */ while (this->lf_index.back().get_sub_offset() != 0) { this->lf_index.pop_back(); } this->lf_index.pop_back(); } else { off = 0; } last_off = off; while (this->lf_line_buffer.read_line(off, lv)) { char tmp = lv.lv_start[lv.lv_len]; this->lf_partial_line = lv.lv_partial; lv.lv_start[lv.lv_len] = '\0'; this->process_prefix(last_off, lv.lv_start, lv.lv_len); lv.lv_start[lv.lv_len] = tmp; last_off = off; if (lo != NULL) { lo->logfile_indexing( *this, this->lf_line_buffer.get_read_offset(off), st.st_size); } } /* * The file can still grow between the above fstat and when we're * doing the scanning, so use the line buffer's notion of the file * size. */ this->lf_index_size = off; // this->lf_line_buffer.invalidate(); retval = true; } this->lf_index_time = this->lf_line_buffer.get_file_time(); if (!this->lf_index_time) { this->lf_index_time = st.st_mtime; } return retval; } logfile_filter::type_t logfile::check_filter(iterator ll, uint8_t generation, const filter_stack_t &filters) { logfile_filter::type_t retval; uint8_t this_generation = ll->get_filter_generation(); if (this_generation == generation) { return ll->get_filter_state(); } else { retval = logfile_filter::MAYBE; } string line_value; for (size_t lpc = 0; lpc < filters.size(); lpc++) { logfile_filter *filter = filters[lpc]; bool matched; if (!filter->is_enabled()) continue; if (line_value.empty()) this->read_line(ll, line_value); matched = filter->matches(*ll, line_value); switch (filter->get_type()) { case logfile_filter::INCLUDE: if (matched) { // Always prefer including something. retval = logfile_filter::INCLUDE; } else if (retval == logfile_filter::MAYBE) { // Only exclude if we haven't made a decision yet. retval = logfile_filter::EXCLUDE; } break; case logfile_filter::EXCLUDE: if (matched && retval == logfile_filter::MAYBE) { // Only exclude if we haven't decide to include the line. retval = logfile_filter::EXCLUDE; } break; default: require(0); break; } } ll->set_filter_state(generation, retval); return retval; } void logfile::read_line(logfile::iterator ll, string &line_out) { try { off_t off = ll->get_offset(); shared_buffer_ref sbr; line_out.clear(); if (this->lf_line_buffer.read_line(off, sbr)) { ostringstream stream; if (this->lf_format.get() != NULL) { this->lf_format->get_subline(*ll, sbr); } line_out.append(sbr.get_data(), sbr.length()); } else { /* XXX */ } } catch (line_buffer::error & e) { /* ... */ } } bool logfile::read_line(logfile::iterator ll, shared_buffer_ref &sbr) { try { off_t off = ll->get_offset(); if (this->lf_line_buffer.read_line(off, sbr)) { if (this->lf_format.get() != NULL) { this->lf_format->get_subline(*ll, sbr); } return true; } } catch (line_buffer::error & e) { } return false; } void logfile::read_full_message(logfile::iterator ll, string &msg_out, int max_lines) { ostringstream stream; do { try { off_t off = ll->get_offset(); shared_buffer_ref sbr; if (stream.tellp() > 0) { stream.write("\n", 1); } if (this->lf_line_buffer.read_line(off, sbr)) { this->lf_format->get_subline(*ll, sbr); stream.write(sbr.get_data(), sbr.length()); } else { /* XXX */ } } catch (line_buffer::error & e) { /* ... */ } ++ll; max_lines -= 1; } while (ll != this->end() && ll->is_continued() && (max_lines == -1 || max_lines > 0)); msg_out = stream.str(); } void logfile::read_full_message(logfile::iterator ll, shared_buffer_ref &msg_out, int max_lines) { require(ll->get_sub_offset() == 0); size_t line_len = this->line_length(ll); try { off_t off = ll->get_offset(); if (this->lf_line_buffer.read_range(off, line_len, msg_out)) { if (this->lf_format.get() != NULL) { this->lf_format->get_subline(*ll, msg_out); } } else { /* XXX */ } } catch (line_buffer::error & e) { /* ... */ } } lnav-0.7.0/src/logfile.hh000664 000765 000024 00000024233 12311035743 015464 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file logfile.hh */ #ifndef __logfile_hh #define __logfile_hh #include #include #include #include #include #include #include #include "lnav_log.hh" #include "byte_array.hh" #include "line_buffer.hh" #include "log_format.hh" #include "shared_buffer.hh" class logfile; /** * Observer interface for logfile indexing progress. * * @see logfile */ class logfile_observer { public: virtual ~logfile_observer() { }; /** * @param lf The logfile object that is doing the indexing. * @param off The current offset in the file being processed. * @param total The total size of the file. */ virtual void logfile_indexing(logfile &lf, off_t off, size_t total) = 0; }; /** * Container for the lines in a log file and some metadata. */ class logfile { public: class error { public: error(std::string filename, int err) : e_filename(filename), e_err(err) { }; std::string e_filename; int e_err; }; typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; /** * Construct a logfile with the given arguments. * * @param filename The name of the log file. * @param fd The file descriptor for accessing the file or -1 if the * constructor should open the file specified by 'filename'. The * descriptor needs to be seekable. */ logfile(std::string filename, auto_fd fd = -1) throw (error); virtual ~logfile(); /** @return The filename as given in the constructor. */ const std::string &get_filename() const { return this->lf_filename; }; int get_fd() const { return this->lf_line_buffer.get_fd(); }; /** @param filename The new filename for this log file. */ void set_filename(const std::string &filename) { this->lf_filename = filename; }; const std::string &get_content_id() const { return this->lf_content_id; }; /** @return The inode for this log file. */ const struct stat &get_stat() const { return this->lf_stat; }; bool is_compressed() const { return this->lf_line_buffer.is_compressed(); }; /** * @return The detected format, rebuild_index() must be called before this * will return a value other than NULL. */ log_format *get_format() const { return this->lf_format.get(); }; /** * @return The last modified time of the file when the file was last * indexed. */ time_t get_modified_time() const { return this->lf_index_time; }; int get_time_offset_line() const { return this->lf_time_offset_line; }; const struct timeval &get_time_offset() const { return this->lf_time_offset; }; void adjust_content_time(int line, const struct timeval &tv, bool abs_offset=true) { struct timeval old_time = this->lf_time_offset; this->lf_time_offset_line = line; if (abs_offset) { this->lf_time_offset = tv; } else { timeradd(&old_time, &tv, &this->lf_time_offset); } for (iterator iter = this->begin(); iter != this->end(); ++iter) { struct timeval curr, diff, new_time; curr = iter->get_timeval(); timersub(&curr, &old_time, &diff); timeradd(&diff, &this->lf_time_offset, &new_time); iter->set_time(new_time); } }; void clear_time_offset(void) { struct timeval tv = { 0, 0 }; this->adjust_content_time(-1, tv); }; bool is_time_adjusted(void) const { return (this->lf_time_offset.tv_sec != 0 || this->lf_time_offset.tv_usec != 0); } iterator begin() { return this->lf_index.begin(); } const_iterator begin() const { return this->lf_index.begin(); } iterator end() { return this->lf_index.end(); } const_iterator end() const { return this->lf_index.end(); } /** @return The number of lines in the index. */ size_t size() { return this->lf_index.size(); } logline &operator[](int index) { return this->lf_index[index]; }; /** @return True if this log file still exists. */ bool exists() const; void close() { this->lf_is_closed = true; }; bool is_closed() const { return this->lf_is_closed; }; struct timeval original_line_time(iterator ll) { if (this->is_time_adjusted()) { struct timeval line_time = ll->get_timeval(); struct timeval retval; timersub(&line_time, &this->lf_time_offset, &retval); return retval; } return ll->get_timeval(); }; /** * Read a line from the file. * * @param ll The line to read. * @param line_out Storage to hold the line itself. */ void read_line(iterator ll, std::string &line_out); bool read_line(iterator ll, shared_buffer_ref &sbr); /** * Read a line from the file. * * @param ll The line to read. * @return The contents of the line as a string. */ std::string read_line(iterator ll) { std::string retval; this->read_line(ll, retval); return retval; }; iterator line_base(iterator ll) { iterator retval = ll; while (retval != this->begin() && retval->get_sub_offset() != 0) { --retval; } return retval; }; size_t line_length(iterator ll) { iterator next_line = ll; size_t retval; do { ++next_line; } while (next_line != this->end() && ll->get_offset() == next_line->get_offset()); if (next_line == this->end()) { retval = this->lf_index_size - ll->get_offset(); if (retval > 0 && !this->lf_partial_line) { retval -= 1; } } else { retval = next_line->get_offset() - ll->get_offset() - 1; } return retval; }; void read_full_message(iterator ll, std::string &msg_out, int max_lines=50); void read_full_message(iterator ll, shared_buffer_ref &msg_out, int max_lines=50); /** * Index any new data in the log file. * * @param lo The observer object that will be called regularly during * indexing. * @return True if any new lines were indexed. */ bool rebuild_index(logfile_observer *lo = NULL) throw (line_buffer::error, logfile::error); /** * Check a line to see if it should be filtered out or not. * * XXX This code doesn't really belong here, it's something more * approprtiate for the logfile_sub_source. The reason it is here right * now is because we cache the result of the check in the logline object. * * @param ll The log line to check. * @param generation The "generation" that the given filters belong to. * If the cached value for this check is from the same * filter generation, then we just return the cached * value. * @param filters The filters to apply. * @return Whether or not the line should be included in the * view. */ logfile_filter::type_t check_filter(iterator ll, uint8_t generation, const filter_stack_t &filters); bool operator<(const logfile &rhs) const { bool retval; if (this->lf_index.empty()) { retval = true; } else if (rhs.lf_index.empty()) { retval = false; } else { retval = this->lf_index[0].get_time() < rhs.lf_index[0].get_time(); } return retval; }; /** Check the invariants for this object. */ bool invariant(void) { require(this->lf_filename.size() > 0); return true; }; protected: /** * Process a line from the file. * * @param offset The offset of the line in the file. * @param prefix The contents of the line. * @param len The length of the 'prefix' string. */ void process_prefix(off_t offset, char *prefix, int len); bool lf_valid_filename; std::string lf_filename; std::string lf_content_id; struct stat lf_stat; std::auto_ptr lf_format; std::vector lf_index; time_t lf_index_time; off_t lf_index_size; line_buffer lf_line_buffer; int lf_time_offset_line; struct timeval lf_time_offset; bool lf_is_closed; bool lf_partial_line; }; #endif lnav-0.7.0/src/logfile_sub_source.cc000664 000765 000024 00000056077 12313212513 017710 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include "k_merge_tree.h" #include "lnav_util.hh" #include "log_accel.hh" #include "logfile_sub_source.hh" using namespace std; #if 0 /* XXX */ class logfile_scrub_map { public: static logfile_scrub_map &singleton() { static logfile_scrub_map s_lsm; return s_lsm; }; const pcre *include(logfile::format_t format) const { map::const_iterator iter; pcre *retval = NULL; if ((iter = this->lsm_include.find(format)) != this->lsm_include.end()) { retval = iter->second; } return retval; }; const pcre *exclude(logfile::format_t format) const { map::const_iterator iter; pcre *retval = NULL; if ((iter = this->lsm_exclude.find(format)) != this->lsm_exclude.end()) { retval = iter->second; } return retval; }; private: pcre *build_pcre(const char *pattern) { const char *errptr; pcre * retval; int eoff; retval = pcre_compile(pattern, PCRE_CASELESS, &errptr, &eoff, NULL); if (retval == NULL) { throw errptr; } return retval; }; logfile_scrub_map() { this->lsm_include[logfile::FORMAT_JBOSS] = this-> build_pcre( "\\d+-(\\d+-\\d+ \\d+:\\d+:\\d+),\\d+ [^ ]+( .*)"); this->lsm_exclude[logfile::FORMAT_JBOSS] = this-> build_pcre("(?:" "\\[((?:[0-9a-zA-Z]+\\.)+)\\w+" "|\\[[\\w: ]+ ((?:[0-9a-zA-Z]+\\.)+)\\w+[^ \\]]+" "| ((?:[0-9a-zA-Z]+\\.)+)\\w+\\])"); this->lsm_include[logfile::FORMAT_SYSLOG] = this-> build_pcre( "(\\w+\\s[\\s\\d]\\d \\d+:\\d+:\\d+) \\w+( .*)"); }; map lsm_include; map lsm_exclude; }; #endif bookmark_type_t logfile_sub_source::BM_ERRORS; bookmark_type_t logfile_sub_source::BM_WARNINGS; bookmark_type_t logfile_sub_source::BM_FILES; logfile_sub_source::logfile_sub_source() : lss_flags(0), lss_filter_generation(1), lss_filtered_count(0) { this->clear_line_size_cache(); } logfile_sub_source::~logfile_sub_source() { } logfile *logfile_sub_source::find(const char *fn, content_line_t &line_base) { std::vector::iterator iter; logfile *retval = NULL; line_base = content_line_t(0); for (iter = this->lss_files.begin(); iter != this->lss_files.end() && retval == NULL; iter++) { if (strcmp(iter->ld_file->get_filename().c_str(), fn) == 0) { retval = iter->ld_file; } else { line_base += content_line_t(MAX_LINES_PER_FILE); } } return retval; } vis_line_t logfile_sub_source::find_from_time(const struct timeval &start) { vector::iterator lb; vis_line_t retval(-1); lb = lower_bound(this->lss_index.begin(), this->lss_index.end(), start, logline_cmp(*this)); if (lb != this->lss_index.end()) { retval = vis_line_t(lb - this->lss_index.begin()); } return retval; } void logfile_sub_source::text_value_for_line(textview_curses &tc, int row, string &value_out, bool raw) { content_line_t line(0); require(row >= 0); require((size_t)row < this->lss_index.size()); line = this->at(vis_line_t(row)); this->lss_token_file = this->find(line); this->lss_token_line = this->lss_token_file->begin() + line; this->lss_token_offset = 0; this->lss_scrub_len = 0; if (raw) { this->lss_token_file->read_line(this->lss_token_line, value_out); return; } this->lss_share_manager.invalidate_refs(); this->lss_token_value = this->lss_token_file->read_line(this->lss_token_line); this->lss_token_date_end = 0; value_out = this->lss_token_value; if (this->lss_flags & F_SCRUB) { log_format *lf = this->lss_token_file->get_format(); lf->scrub(value_out); } if (this->lss_token_file->is_time_adjusted() && !(this->lss_token_line->get_level() & logline::LEVEL_CONTINUED)) { log_format *format = this->lss_token_file->get_format(); if (format->lf_date_time.dts_fmt_lock != -1) { shared_buffer_ref sbr; std::vector line_values; struct timeval adjusted_time; string_attrs_t sa; char buffer[128]; const char *fmt; fmt = std_time_fmt[format->lf_date_time.dts_fmt_lock]; adjusted_time = this->lss_token_line->get_timeval(); strftime(buffer, sizeof(buffer), fmt, gmtime(&adjusted_time.tv_sec)); sbr.share(this->lss_share_manager, (char *)this->lss_token_value.c_str(), this->lss_token_value.size()); format->annotate(sbr, sa, line_values); struct line_range time_range; time_range = find_string_attr_range(sa, &logline::L_TIMESTAMP); if (time_range.lr_start != -1) { const char *last = value_out.c_str(); int len = strlen(buffer); if ((last[time_range.lr_start + len] == '.' || last[time_range.lr_start + len] == ',') && len + 4 <= time_range.length()) { snprintf(&buffer[len], sizeof(buffer) - len, ".%03d", this->lss_token_line->get_millis()); } value_out.replace(time_range.lr_start, strlen(buffer), string(buffer)); } } } if (this->lss_flags & F_TIME_OFFSET) { int64_t start_millis, curr_millis; vis_line_t prev_mark = tc.get_bookmarks()[&textview_curses::BM_USER].prev(vis_line_t(row)); if (prev_mark == -1) { prev_mark = vis_line_t(0); } logline *first_line = this->find_line(this->at(prev_mark)); start_millis = first_line->get_time_in_millis(); curr_millis = this->lss_token_line->get_time_in_millis(); int64_t diff = curr_millis - start_millis; /* 24h22m33s111 */ static struct rel_interval { long long length; const char *format; const char *symbol; } intervals[] = { { 1000, "%03qd%s", "" }, { 60, "%qd%s", "s" }, { 60, "%qd%s", "m" }, { 0, "%qd%s", "h" }, { 0, NULL, NULL } }; struct rel_interval *curr_interval; int rel_length = 0; value_out = "|" + value_out; for (curr_interval = intervals; curr_interval->symbol != NULL; curr_interval++) { long long amount; char segment[32]; if (curr_interval->length) { amount = diff % curr_interval->length; diff = diff / curr_interval->length; } else { amount = diff; diff = 0; } if (!amount && !diff) { break; } snprintf(segment, sizeof(segment), curr_interval->format, amount, curr_interval->symbol); rel_length += strlen(segment); value_out = segment + value_out; } if (rel_length < 12) { value_out.insert(0, 12 - rel_length, ' '); } } } void logfile_sub_source::text_attrs_for_line(textview_curses &lv, int row, string_attrs_t &value_out) { view_colors & vc = view_colors::singleton(); logline * next_line = NULL; struct line_range lr; int time_offset_end = 0; int attrs = 0; switch (this->lss_token_line->get_level() & ~logline::LEVEL__FLAGS) { case logline::LEVEL_FATAL: case logline::LEVEL_CRITICAL: case logline::LEVEL_ERROR: attrs = vc.attrs_for_role(view_colors::VCR_ERROR); break; case logline::LEVEL_WARNING: attrs = vc.attrs_for_role(view_colors::VCR_WARNING); break; default: attrs = vc.attrs_for_role(view_colors::VCR_TEXT); break; } if ((row + 1) < (int)this->lss_index.size()) { next_line = this->find_line(this->at(vis_line_t(row + 1))); } if (next_line != NULL && (day_num(next_line->get_time()) > day_num(this->lss_token_line->get_time()))) { attrs |= A_UNDERLINE; } log_format *format = this->lss_token_file->get_format(); std::vector line_values; if (!(this->lss_token_line->get_level() & logline::LEVEL_CONTINUED)) { shared_buffer_ref sbr; sbr.share(this->lss_share_manager, (char *)this->lss_token_value.c_str(), this->lss_token_value.size()); format->annotate(sbr, value_out, line_values); } lr.lr_start = time_offset_end + this->lss_token_date_end; lr.lr_end = -1; value_out.push_back(string_attr(lr, &view_curses::VC_STYLE, attrs)); if (this->lss_flags & F_TIME_OFFSET) { time_offset_end = 13; lr.lr_start = 0; lr.lr_end = time_offset_end; for (string_attrs_t::iterator iter = value_out.begin(); iter != value_out.end(); ++iter) { struct line_range *existing_lr = (line_range *)&iter->sa_range; existing_lr->lr_start += time_offset_end; if (existing_lr->lr_end != -1) { existing_lr->lr_end += time_offset_end; } } // attrs = vc.attrs_for_role(view_colors::VCR_OK); attrs = view_colors::ansi_color_pair(COLOR_CYAN, COLOR_BLACK); value_out.push_back(string_attr(lr, &view_curses::VC_STYLE, attrs)); value_out.push_back(string_attr(line_range(12, 13), &view_curses::VC_GRAPHIC, ACS_VLINE)); int bar_attrs = 0; switch (this->get_line_accel_direction(vis_line_t(row))) { case log_accel::A_STEADY: break; case log_accel::A_DECEL: bar_attrs = view_colors::ansi_color_pair(COLOR_RED, COLOR_BLACK); break; case log_accel::A_ACCEL: bar_attrs = view_colors::ansi_color_pair(COLOR_GREEN, COLOR_BLACK); break; } value_out.push_back( string_attr(line_range(12, 13), &view_curses::VC_STYLE, bar_attrs)); } lr.lr_start = 0; lr.lr_end = -1; value_out.push_back(string_attr(lr, &logline::L_FILE, this->lss_token_file)); { bookmark_vector &bv = lv.get_bookmarks()[&textview_curses::BM_PARTITION]; bookmark_vector::iterator bv_iter; bv_iter = lower_bound(bv.begin(), bv.end(), vis_line_t(row + 1)); if (bv_iter != bv.begin()) { --bv_iter; content_line_t part_start_line = this->at(*bv_iter); std::map::iterator bm_iter; if ((bm_iter = this->lss_user_mark_metadata.find(part_start_line)) != this->lss_user_mark_metadata.end()) { lr.lr_start = 0; lr.lr_end = -1; value_out.push_back(string_attr(lr, &logline::L_PARTITION, &bm_iter->second)); } } } if (this->lss_token_file->is_time_adjusted()) { struct line_range time_range = find_string_attr_range( value_out, &logline::L_TIMESTAMP); if (time_range.lr_end != -1) { attrs = vc.attrs_for_role(view_colors::VCR_ADJUSTED_TIME); value_out.push_back(string_attr(time_range, &view_curses::VC_STYLE, attrs)); } } else if ((((this->lss_token_line->get_time() / (5 * 60)) % 2) == 0) && !(this->lss_token_line->get_level() & logline::LEVEL_CONTINUED)) { struct line_range time_range = find_string_attr_range( value_out, &logline::L_TIMESTAMP); if (time_range.lr_end != -1) { attrs = vc.attrs_for_role(view_colors::VCR_ALT_ROW); value_out.push_back(string_attr(time_range, &view_curses::VC_STYLE, attrs)); } } } bool logfile_sub_source::rebuild_index(observer *obs, bool force) { std::vector::iterator iter; size_t total_lines = 0; bool retval = force; int file_count = 0; for (iter = this->lss_files.begin(); iter != this->lss_files.end(); iter++) { if (iter->ld_file == NULL) { if (iter->ld_lines_indexed > 0) { force = true; retval = true; } } else { if (iter->ld_file->rebuild_index(obs)) { retval = true; } file_count += 1; total_lines += iter->ld_file->size(); } } if (force) { for (iter = this->lss_files.begin(); iter != this->lss_files.end(); iter++) { iter->ld_lines_indexed = 0; } } if (retval || force) { size_t index_size = 0; if (force) { this->lss_index.clear(); this->lss_filtered_count = 0; } kmerge_tree_c merge(file_count); for (iter = this->lss_files.begin(); iter != this->lss_files.end(); iter++) { if (iter->ld_file == NULL) continue; merge.add(&(*iter), iter->ld_file->begin() + iter->ld_lines_indexed, iter->ld_file->end()); index_size += iter->ld_file->size(); } this->lss_index.reserve(index_size); logfile_filter::type_t action_for_prev_line = logfile_filter::MAYBE; logfile_data *last_owner = NULL; merge.execute(); for (;;) { logfile::iterator lf_iter; logfile_data *ld; if (!merge.get_top(ld, lf_iter)) { break; } int file_index = ld - &(*this->lss_files.begin()); int line_index = lf_iter - ld->ld_file->begin(); content_line_t con_line(file_index * MAX_LINES_PER_FILE + line_index); if (!(lf_iter->get_level() & logline::LEVEL_CONTINUED)) { if (last_owner != NULL) { if (action_for_prev_line != logfile_filter::EXCLUDE) { // Append all of the lines from the previous message. while (last_owner->ld_indexing.ld_start <= last_owner->ld_indexing.ld_last) { this->lss_index.push_back(last_owner->ld_indexing.ld_start); ++last_owner->ld_indexing.ld_start; } } else { this->lss_filtered_count += 1; } } ld->ld_indexing.ld_start = con_line; action_for_prev_line = logfile_filter::MAYBE; } if (obs != NULL) { obs->logfile_sub_source_filtering( *this, vis_line_t(this->lss_index.size()), total_lines); } ld->ld_indexing.ld_last = con_line; if (action_for_prev_line != logfile_filter::INCLUDE) { // We haven't decided to include yet, so check the filter again. // Once we decide to include a sub-line, the whole log message will // always be included. logfile_filter::type_t action_for_this_line = ld->ld_file->check_filter( lf_iter, this->lss_filter_generation, this->lss_filters); // Only record the filter results for this line if it's not decisive. if (action_for_this_line != logfile_filter::MAYBE) { action_for_prev_line = action_for_this_line; } } last_owner = ld; merge.next(); } if (obs != NULL) { obs->logfile_sub_source_filtering(*this, vis_line_t(total_lines - 1), total_lines); } if (last_owner != NULL) { if (action_for_prev_line != logfile_filter::EXCLUDE) { while (last_owner->ld_indexing.ld_start <= last_owner->ld_indexing.ld_last) { this->lss_index.push_back(last_owner->ld_indexing.ld_start); ++last_owner->ld_indexing.ld_start; } } else { this->lss_filtered_count += 1; } } for (iter = this->lss_files.begin(); iter != this->lss_files.end(); iter++) { if (iter->ld_file == NULL) continue; iter->ld_lines_indexed = iter->ld_file->size(); } } return retval; } void logfile_sub_source::text_update_marks(vis_bookmarks &bm) { logfile * last_file = NULL; vis_line_t vl; bm[&BM_WARNINGS].clear(); bm[&BM_ERRORS].clear(); bm[&BM_FILES].clear(); for (bookmarks::type::iterator iter = this->lss_user_marks.begin(); iter != this->lss_user_marks.end(); ++iter) { bm[iter->first].clear(); } for (; vl < (int)this->lss_index.size(); ++vl) { const content_line_t orig_cl = this->at(vl); content_line_t cl = orig_cl; logfile * lf; lf = this->find(cl); for (bookmarks::type::iterator iter = this->lss_user_marks.begin(); iter != this->lss_user_marks.end(); ++iter) { if (binary_search(iter->second.begin(), iter->second.end(), orig_cl)) { bm[iter->first].insert_once(vl); if (iter->first == &textview_curses::BM_USER) { logfile::iterator ll = lf->begin() + cl; ll->set_mark(true); } } } if (lf != last_file) { bm[&BM_FILES].insert_once(vl); } switch ((*lf)[cl].get_level() & ~logline::LEVEL_MARK) { case logline::LEVEL_WARNING: bm[&BM_WARNINGS].insert_once(vl); break; case logline::LEVEL_FATAL: case logline::LEVEL_ERROR: case logline::LEVEL_CRITICAL: bm[&BM_ERRORS].insert_once(vl); break; default: break; } last_file = lf; } } log_accel::direction_t logfile_sub_source::get_line_accel_direction( vis_line_t vl) { log_accel la; while (vl >= 0) { logline *curr_line = this->find_line(this->at(vl)); if (curr_line->is_continued()) { --vl; continue; } if (!la.add_point(curr_line->get_time_in_millis())) { break; } --vl; } return la.get_direction(); } #if 0 void logfile_sub_source::handle_scroll(listview_curses *lc) { printf("hello, world!\n"); return; vis_line_t top = lc->get_top(); if (this->lss_index.empty()) { this->lss_top_time = -1; this->lss_bottom_time = -1; } else { time_t top_day, bottom_day, today, yesterday, now = time(NULL); vis_line_t bottom(0), height(0); unsigned long width; char status[32]; logline * ll; today = day_num(now); yesterday = today - 1; lc->get_dimensions(height, width); ll = this->find_line(this->lss_index[top]); this->lss_top_time = ll->get_time(); bottom = min(top + height - vis_line_t(1), vis_line_t(this->lss_index.size() - 1)); ll = this->find_line(this->lss_index[bottom]); this->lss_bottom_time = ll->get_time(); top_day = day_num(this->lss_top_time); bottom_day = day_num(this->lss_bottom_time); if (top_day == today) { snprintf(status, sizeof(status), "Today"); } else if (top_day == yesterday) { snprintf(status, sizeof(status), "Yesterday"); } else { strftime(status, sizeof(status), "%a %b %d", gmtime(&this->lss_top_time)); } if (top_day != bottom_day) { int len = strlen(status); if (bottom_day == today) { snprintf(&status[len], sizeof(status) - len, " - Today"); } else if (bottom_day == yesterday) { snprintf(&status[len], sizeof(status) - len, " - Yesterday"); } else { strftime(&status[len], sizeof(status) - len, " - %b %d", gmtime(&this->lss_bottom_time)); } } this->lss_date_field.set_value(string(status)); } } #endif lnav-0.7.0/src/logfile_sub_source.hh000664 000765 000024 00000034341 12311355563 017723 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file logfile_sub_source.hh */ #ifndef __logfile_sub_source_hh #define __logfile_sub_source_hh #include #include #include #include #include #include #include "lnav_log.hh" #include "log_accel.hh" #include "strong_int.hh" #include "logfile.hh" #include "bookmarks.hh" #include "textview_curses.hh" STRONG_INT_TYPE(uint64_t, content_line); /** * Delegate class that merges the contents of multiple log files into a single * source of data for a text view. */ class logfile_sub_source : public text_sub_source { public: class observer : public logfile_observer { public: virtual void logfile_sub_source_filtering(logfile_sub_source &lss, vis_line_t cl, size_t total) = 0; }; static bookmark_type_t BM_ERRORS; static bookmark_type_t BM_WARNINGS; static bookmark_type_t BM_FILES; logfile_sub_source(); virtual ~logfile_sub_source(); const filter_stack_t &get_filters(void) const { return this->lss_filters; }; void add_filter(logfile_filter *filter) { this->lss_filters.push_back(filter); this->lss_filter_generation += 1; }; void clear_filters(void) { this->lss_filters.clear(); this->lss_filter_generation += 1; }; void filter_changed(void) { this->lss_filter_generation += 1; }; void set_filter_enabled(logfile_filter *filter, bool enabled) { if (enabled) { filter->enable(); } else { filter->disable(); } this->lss_filter_generation += 1; } logfile_filter *get_filter(std::string id) { filter_stack_t::iterator iter; logfile_filter * retval = NULL; for (iter = this->lss_filters.begin(); iter != this->lss_filters.end() && (*iter)->get_id() != id; iter++) { } if (iter != this->lss_filters.end()) { retval = *iter; } return retval; }; void toggle_scrub(void) { this->lss_flags ^= F_SCRUB; this->clear_line_size_cache(); }; void toggle_time_offset(void) { this->lss_flags ^= F_TIME_OFFSET; this->clear_line_size_cache(); }; void set_time_offset(bool enabled) { if (enabled) this->lss_flags |= F_TIME_OFFSET; else this->lss_flags &= ~F_TIME_OFFSET; this->clear_line_size_cache(); }; bool is_time_offset_enabled(void) const { return this->lss_flags & F_TIME_OFFSET; }; size_t text_line_count() { return this->lss_index.size(); }; bool empty() const { return this->lss_index.empty(); }; void text_value_for_line(textview_curses &tc, int row, std::string &value_out, bool raw); void text_attrs_for_line(textview_curses &tc, int row, string_attrs_t &value_out); size_t text_size_for_line(textview_curses &tc, int row, bool raw) { size_t index = row % LINE_SIZE_CACHE_SIZE; if (this->lss_line_size_cache[index].first != row) { std::string value; this->text_value_for_line(tc, row, value, raw); this->lss_line_size_cache[index].second = value.size(); this->lss_line_size_cache[index].first = row; } return this->lss_line_size_cache[index].second; }; void text_mark(bookmark_type_t *bm, int line, bool added) { content_line_t cl = this->at(vis_line_t(line)); std::vector::iterator lb; if (bm == &textview_curses::BM_USER) { logline *ll = this->find_line(cl); ll->set_mark(added); } lb = std::lower_bound(this->lss_user_marks[bm].begin(), this->lss_user_marks[bm].end(), cl); if (added) { if (lb == this->lss_user_marks[bm].end() || *lb != cl) { this->lss_user_marks[bm].insert(lb, cl); } } else if (lb != this->lss_user_marks[bm].end() && *lb == cl) { require(lb != this->lss_user_marks[bm].end()); this->lss_user_marks[bm].erase(lb); } }; void text_clear_marks(bookmark_type_t *bm) { std::vector::iterator iter; if (bm == &textview_curses::BM_USER) { for (iter = this->lss_user_marks[bm].begin(); iter != this->lss_user_marks[bm].end(); ++iter) { this->find_line(*iter)->set_mark(false); } } this->lss_user_marks[bm].clear(); }; bool insert_file(logfile *lf) { std::vector::iterator existing; require(lf->size() < MAX_LINES_PER_FILE); existing = std::find_if(this->lss_files.begin(), this->lss_files.end(), logfile_data_eq(NULL)); if (existing == this->lss_files.end()) { if (this->lss_files.size() >= MAX_FILES) { return false; } this->lss_files.push_back(logfile_data(lf)); this->lss_index.clear(); } else { existing->ld_file = lf; } return true; }; void remove_file(logfile *lf) { std::vector::iterator iter; iter = std::find_if(this->lss_files.begin(), this->lss_files.end(), logfile_data_eq(lf)); if (iter != this->lss_files.end()) { bookmarks::type::iterator mark_iter; int file_index = iter - this->lss_files.begin(); iter->clear(); for (mark_iter = this->lss_user_marks.begin(); mark_iter != this->lss_user_marks.end(); ++mark_iter) { content_line_t mark_curr = content_line_t( file_index * MAX_LINES_PER_FILE); content_line_t mark_end = content_line_t( (file_index + 1) * MAX_LINES_PER_FILE); bookmark_vector::iterator bv_iter; bookmark_vector & bv = mark_iter->second; while ((bv_iter = std::lower_bound(bv.begin(), bv.end(), mark_curr)) != bv.end()) { if (*bv_iter >= mark_end) { break; } mark_iter->second.erase(bv_iter); } } } }; bool rebuild_index(observer *obs = NULL, bool force = false); void text_update_marks(vis_bookmarks &bm); void set_user_mark(bookmark_type_t *bm, content_line_t cl) { this->lss_user_marks[bm].insert_once(cl); }; bookmarks::type &get_user_bookmarks(void) { return this->lss_user_marks; }; std::map &get_user_bookmark_metadata(void) { return this->lss_user_mark_metadata; }; int get_filtered_count() const { return this->lss_filtered_count; }; logfile *find(const char *fn, content_line_t &line_base); logfile *find(content_line_t &line) { logfile *retval; retval = this->lss_files[line / MAX_LINES_PER_FILE].ld_file; line = content_line_t(line % MAX_LINES_PER_FILE); return retval; }; logline *find_line(content_line_t line) { logline *retval = NULL; logfile *lf = this->find(line); if (lf != NULL) { logfile::iterator ll_iter = lf->begin() + line; retval = &(*ll_iter); } return retval; }; vis_line_t find_from_time(const struct timeval &start); vis_line_t find_from_time(time_t start) { struct timeval tv = { start, 0 }; return this->find_from_time(tv); }; content_line_t at(vis_line_t vl) { return this->lss_index[vl]; }; content_line_t at_base(vis_line_t vl) { while (this->find_line(this->at(vl))->get_sub_offset() != 0) { --vl; } return this->at(vl); }; log_accel::direction_t get_line_accel_direction(vis_line_t vl); /** * Container for logfile references that keeps of how many lines in the * logfile have been indexed. */ struct logfile_data { logfile_data(logfile *lf = NULL) : ld_file(lf), ld_lines_indexed(0) { }; bool operator<(const logfile_data &rhs) { if (this->ld_file == rhs.ld_file) { return false; } if (this->ld_file == NULL) { return true; } if (this->ld_file != NULL) { return true; } return (*this->ld_file) < (*rhs.ld_file); }; void clear(void) { this->ld_file = NULL; }; logfile *ld_file; size_t ld_lines_indexed; struct { content_line_t ld_start; content_line_t ld_last; } ld_indexing; }; typedef std::vector::iterator iterator; iterator begin() { return this->lss_files.begin(); }; iterator end() { return this->lss_files.end(); }; content_line_t get_file_base_content_line(iterator iter) { int index = std::distance(this->begin(), iter); return content_line_t(index * MAX_LINES_PER_FILE); }; static const uint64_t MAX_CONTENT_LINES = (1ULL << 40) - 1; static const uint64_t MAX_LINES_PER_FILE = 256 * 1024 * 1024; static const uint64_t MAX_FILES = ( MAX_CONTENT_LINES / MAX_LINES_PER_FILE); private: static const size_t LINE_SIZE_CACHE_SIZE = 512; enum { B_SCRUB, B_TIME_OFFSET, }; enum { F_SCRUB = (1L << B_SCRUB), F_TIME_OFFSET = (1L << B_TIME_OFFSET), }; struct __attribute__((__packed__)) indexed_content { indexed_content(content_line_t cl) : ic_value(cl) { }; operator content_line_t () { return content_line_t(this->ic_value); }; uint64_t ic_value : 40; }; struct logline_cmp { logline_cmp(logfile_sub_source & lc) : llss_controller(lc) { }; bool operator()(const content_line_t &lhs, const content_line_t &rhs) { logline *ll_lhs = this->llss_controller.find_line(lhs); logline *ll_rhs = this->llss_controller.find_line(rhs); return (*ll_lhs) < (*ll_rhs); }; #if 0 bool operator()(const indexed_content &lhs, const indexed_content &rhs) { logline *ll_lhs = this->llss_controller.find_line(lhs.ic_value); logline *ll_rhs = this->llss_controller.find_line(rhs.ic_value); return (*ll_lhs) < (*ll_rhs); }; #endif bool operator()(const content_line_t &lhs, const time_t &rhs) { logline *ll_lhs = this->llss_controller.find_line(lhs); return *ll_lhs < rhs; }; bool operator()(const content_line_t &lhs, const struct timeval &rhs) { logline *ll_lhs = this->llss_controller.find_line(lhs); return *ll_lhs < rhs; }; logfile_sub_source & llss_controller; }; /** * Functor for comparing the ld_file field of the logfile_data struct. */ struct logfile_data_eq { logfile_data_eq(logfile *lf) : lde_file(lf) { }; bool operator()(const logfile_data &ld) { return this->lde_file == ld.ld_file; } logfile *lde_file; }; void clear_line_size_cache(void) { memset(this->lss_line_size_cache, 0, sizeof(this->lss_line_size_cache)); this->lss_line_size_cache[0].first = -1; }; unsigned long lss_flags; std::vector lss_files; filter_stack_t lss_filters; uint8_t lss_filter_generation; int lss_filtered_count; std::vector lss_index; bookmarks::type lss_user_marks; std::map lss_user_mark_metadata; logfile * lss_token_file; std::string lss_token_value; shared_buffer lss_share_manager; int lss_scrub_len; int lss_token_offset; int lss_token_date_end; logfile::iterator lss_token_line; std::pair lss_line_size_cache[LINE_SIZE_CACHE_SIZE]; }; #endif lnav-0.7.0/src/Makefile.am000664 000765 000024 00000010744 12313322417 015557 0ustar00stackstaff000000 000000 bin_PROGRAMS = lnav noinst_PROGRAMS = bin2c ptimec lnav-test noinst_LIBRARIES = libdiag.a help.c: $(srcdir)/help.txt bin2c ./bin2c -z -c $(srcdir)/help.txt $@ dump-pid-sh.c: $(srcdir)/dump-pid.sh bin2c ./bin2c -z -c $(srcdir)/dump-pid.sh $@ default-log-formats-json.c: $(srcdir)/default-log-formats.json bin2c ./bin2c -z -c $(srcdir)/default-log-formats.json $@ init.sql: $(srcdir)/init_sql.py $(PYTHON) $(srcdir)/init_sql.py > $@ init-sql.c: $(srcdir)/init.sql bin2c ./bin2c -z -c $(srcdir)/init.sql $@ TIME_FORMATS = \ "%Y-%m-%d %H:%M:%S" \ "%Y-%m-%d %H:%M" \ "%Y-%m-%dT%H:%M:%S" \ "%Y-%m-%dT%H:%M:%SZ" \ "%Y/%m/%d %H:%M:%S" \ "%Y/%m/%d %H:%M" \ "%a %b %d %H:%M:%S %Y" \ "%a %b %d %H:%M:%S %Z %Y" \ "%a %b %d %H:%M:%S " \ "%d/%b/%Y:%H:%M:%S %z" \ "%b %d %H:%M:%S" \ "%m/%d/%y %H:%M:%S" \ "%m%d %H:%M:%S" time_fmts.cc: ptimec ./ptimec $(TIME_FORMATS) > $@ AM_LDFLAGS = \ $(STATIC_LDFLAGS) \ $(SQLITE3_LDFLAGS) \ $(PCRE_LDFLAGS) \ -pthread AM_CPPFLAGS = \ -DSYSCONFDIR='"$(sysconfdir)"' \ -Wall \ $(SQLITE3_CFLAGS) LDADD = \ libdiag.a \ $(READLINE_LIBS) \ $(CURSES_LIB) \ $(SQLITE3_LIBS) \ -lpcrecpp dist_noinst_DATA = \ default-log-formats.json \ dump-pid.sh noinst_HEADERS = \ ansi_scrubber.hh \ auto_fd.hh \ auto_mem.hh \ auto_pid.hh \ bookmarks.hh \ bottom_status_source.hh \ byte_array.hh \ column_namer.hh \ data_scanner.hh \ data_parser.hh \ default-log-formats-json.hh \ db_sub_source.hh \ format-text-files.hh \ grapher.hh \ grep_highlighter.hh \ grep_proc.hh \ help.hh \ help.txt \ hist_source.hh \ init.sql \ init-sql.hh \ k_merge_tree.h \ line_buffer.hh \ listview_curses.hh \ lnav.hh \ lnav_commands.hh \ lnav_config.hh \ lnav_log.hh \ lnav_util.hh \ log_accel.hh \ log_data_helper.hh \ log_data_table.hh \ log_format.hh \ log_format_loader.hh \ logfile.hh \ logfile_sub_source.hh \ pcrepp.hh \ piper_proc.hh \ ptimec.hh \ readline_curses.hh \ readline_highlighters.hh \ sequence_matcher.hh \ sequence_sink.hh \ session_data.hh \ shared_buffer.hh \ sql_util.hh \ sqlite-extension-func.h \ status_controllers.hh \ statusview_curses.hh \ strnatcmp.h \ strong_int.hh \ termios_guard.hh \ term_extra.hh \ textfile_sub_source.hh \ textview_curses.hh \ time_T.hh \ top_status_source.hh \ view_curses.hh \ vt52_curses.hh \ log_vtab_impl.hh \ log_format_impls.cc \ xterm_mouse.hh \ yajlpp.hh \ yajl/api/yajl_common.h \ yajl/api/yajl_gen.h \ yajl/api/yajl_parse.h \ yajl/api/yajl_tree.h \ yajl/yajl_alloc.h \ yajl/yajl_buf.h \ yajl/yajl_bytestack.h \ yajl/yajl_common.h \ yajl/yajl_encode.h \ yajl/yajl_lex.h \ yajl/yajl_parser.h \ yajl/yajl_version.h \ spookyhash/SpookyV2.h libdiag_a_SOURCES = \ ansi_scrubber.cc \ bookmarks.cc \ collation-functions.cc \ db_sub_source.cc \ extension-functions.c \ fs-extension-functions.cc \ grep_proc.cc \ hist_source.cc \ line_buffer.cc \ listview_curses.cc \ lnav_commands.cc \ lnav_config.cc \ lnav_log.cc \ lnav_util.cc \ log_accel.cc \ log_format.cc \ log_format_loader.cc \ logfile.cc \ logfile_sub_source.cc \ network-extension-functions.cc \ data_scanner.cc \ data_parser.cc \ ptimec_rt.cc \ readline_curses.cc \ readline_highlighters.cc \ session_data.cc \ sequence_matcher.cc \ shared_buffer.cc \ sqlite-extension-func.c \ statusview_curses.cc \ string-extension-functions.cc \ pcrepp.cc \ piper_proc.cc \ sql_util.cc \ state-extension-functions.cc \ strnatcmp.c \ textview_curses.cc \ time_fmts.cc \ view_curses.cc \ vt52_curses.cc \ log_vtab_impl.cc \ xterm_mouse.cc \ yajlpp.cc \ yajl/yajl.c \ yajl/yajl_alloc.c \ yajl/yajl_alloc.h \ yajl/yajl_buf.c \ yajl/yajl_buf.h \ yajl/yajl_bytestack.h \ yajl/yajl_encode.c \ yajl/yajl_encode.h \ yajl/yajl_gen.c \ yajl/yajl_lex.c \ yajl/yajl_lex.h \ yajl/yajl_parser.c \ yajl/yajl_parser.h \ yajl/yajl_tree.c \ yajl/yajl_version.c \ spookyhash/SpookyV2.cpp dist_noinst_SCRIPTS = \ init_sql.py TEXT2C_FILES = \ dump-pid-sh.o \ help.o \ init-sql.o \ default-log-formats-json.o lnav_SOURCES = lnav.cc $(HELP_SRC) lnav_LDADD = \ $(TEXT2C_FILES) \ $(LDADD) lnav_test_SOURCES = lnav.cc $(HELP_SRC) test_override.cc lnav_test_LDADD = \ $(TEXT2C_FILES) \ $(LDADD) bin2c_SOURCES = bin2c.c bin2c_LDADD = ptimec_SOURCES = ptimec.cc ptimec_LDADD = DISTCLEANFILES = \ dump-pid-sh.c \ help.c \ init-sql.c \ default-log-formats-json.c \ time_fmts.cc uncrusty: (cd $(srcdir) && uncrustify -c ../lnav.cfg --replace $(SOURCES) \ $(HEADERS)) lnav-0.7.0/src/Makefile.in000664 000765 000024 00000104656 12313323142 015572 0ustar00stackstaff000000 000000 # Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = lnav$(EXEEXT) noinst_PROGRAMS = bin2c$(EXEEXT) ptimec$(EXEEXT) lnav-test$(EXEEXT) subdir = src DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(srcdir)/config.h.in $(top_srcdir)/mkinstalldirs \ $(dist_noinst_SCRIPTS) $(top_srcdir)/depcomp \ $(dist_noinst_DATA) $(noinst_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/ax_sqlite3.m4 \ $(top_srcdir)/ax_with_curses.m4 $(top_srcdir)/lnav.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) AR = ar ARFLAGS = cru AM_V_AR = $(am__v_AR_@AM_V@) am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = libdiag_a_AR = $(AR) $(ARFLAGS) libdiag_a_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp am_libdiag_a_OBJECTS = ansi_scrubber.$(OBJEXT) bookmarks.$(OBJEXT) \ collation-functions.$(OBJEXT) db_sub_source.$(OBJEXT) \ extension-functions.$(OBJEXT) fs-extension-functions.$(OBJEXT) \ grep_proc.$(OBJEXT) hist_source.$(OBJEXT) \ line_buffer.$(OBJEXT) listview_curses.$(OBJEXT) \ lnav_commands.$(OBJEXT) lnav_config.$(OBJEXT) \ lnav_log.$(OBJEXT) lnav_util.$(OBJEXT) log_accel.$(OBJEXT) \ log_format.$(OBJEXT) log_format_loader.$(OBJEXT) \ logfile.$(OBJEXT) logfile_sub_source.$(OBJEXT) \ network-extension-functions.$(OBJEXT) data_scanner.$(OBJEXT) \ data_parser.$(OBJEXT) ptimec_rt.$(OBJEXT) \ readline_curses.$(OBJEXT) readline_highlighters.$(OBJEXT) \ session_data.$(OBJEXT) sequence_matcher.$(OBJEXT) \ shared_buffer.$(OBJEXT) sqlite-extension-func.$(OBJEXT) \ statusview_curses.$(OBJEXT) \ string-extension-functions.$(OBJEXT) pcrepp.$(OBJEXT) \ piper_proc.$(OBJEXT) sql_util.$(OBJEXT) \ state-extension-functions.$(OBJEXT) strnatcmp.$(OBJEXT) \ textview_curses.$(OBJEXT) time_fmts.$(OBJEXT) \ view_curses.$(OBJEXT) vt52_curses.$(OBJEXT) \ log_vtab_impl.$(OBJEXT) xterm_mouse.$(OBJEXT) yajlpp.$(OBJEXT) \ yajl/yajl.$(OBJEXT) yajl/yajl_alloc.$(OBJEXT) \ yajl/yajl_buf.$(OBJEXT) yajl/yajl_encode.$(OBJEXT) \ yajl/yajl_gen.$(OBJEXT) yajl/yajl_lex.$(OBJEXT) \ yajl/yajl_parser.$(OBJEXT) yajl/yajl_tree.$(OBJEXT) \ yajl/yajl_version.$(OBJEXT) spookyhash/SpookyV2.$(OBJEXT) libdiag_a_OBJECTS = $(am_libdiag_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am_bin2c_OBJECTS = bin2c.$(OBJEXT) bin2c_OBJECTS = $(am_bin2c_OBJECTS) bin2c_DEPENDENCIES = am_lnav_OBJECTS = lnav.$(OBJEXT) lnav_OBJECTS = $(am_lnav_OBJECTS) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = libdiag.a $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) lnav_DEPENDENCIES = $(TEXT2C_FILES) $(am__DEPENDENCIES_2) am_lnav_test_OBJECTS = lnav.$(OBJEXT) test_override.$(OBJEXT) lnav_test_OBJECTS = $(am_lnav_test_OBJECTS) lnav_test_DEPENDENCIES = $(TEXT2C_FILES) $(am__DEPENDENCIES_2) am_ptimec_OBJECTS = ptimec.$(OBJEXT) ptimec_OBJECTS = $(am_ptimec_OBJECTS) ptimec_DEPENDENCIES = SCRIPTS = $(dist_noinst_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ 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) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libdiag_a_SOURCES) $(bin2c_SOURCES) $(lnav_SOURCES) \ $(lnav_test_SOURCES) $(ptimec_SOURCES) DIST_SOURCES = $(libdiag_a_SOURCES) $(bin2c_SOURCES) $(lnav_SOURCES) \ $(lnav_test_SOURCES) $(ptimec_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(dist_noinst_DATA) HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BZIP2_CMD = @BZIP2_CMD@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CFLAGS_PG = @CFLAGS_PG@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CURSES_LIB = @CURSES_LIB@ CXX = @CXX@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ 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@ 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@ PCRE_CFLAGS = @PCRE_CFLAGS@ PCRE_LIBS = @PCRE_LIBS@ PYTHON = @PYTHON@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ RANLIB = @RANLIB@ READLINE_CFLAGS = @READLINE_CFLAGS@ READLINE_LIBS = @READLINE_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SQLITE3_CFLAGS = @SQLITE3_CFLAGS@ SQLITE3_CMD = @SQLITE3_CMD@ SQLITE3_LDFLAGS = @SQLITE3_LDFLAGS@ SQLITE3_LIBS = @SQLITE3_LIBS@ SQLITE3_VERSION = @SQLITE3_VERSION@ STATIC_LDFLAGS = @STATIC_LDFLAGS@ STRIP = @STRIP@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ abssrcdir = @abssrcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ 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@ noinst_LIBRARIES = libdiag.a TIME_FORMATS = \ "%Y-%m-%d %H:%M:%S" \ "%Y-%m-%d %H:%M" \ "%Y-%m-%dT%H:%M:%S" \ "%Y-%m-%dT%H:%M:%SZ" \ "%Y/%m/%d %H:%M:%S" \ "%Y/%m/%d %H:%M" \ "%a %b %d %H:%M:%S %Y" \ "%a %b %d %H:%M:%S %Z %Y" \ "%a %b %d %H:%M:%S " \ "%d/%b/%Y:%H:%M:%S %z" \ "%b %d %H:%M:%S" \ "%m/%d/%y %H:%M:%S" \ "%m%d %H:%M:%S" AM_LDFLAGS = \ $(STATIC_LDFLAGS) \ $(SQLITE3_LDFLAGS) \ $(PCRE_LDFLAGS) \ -pthread AM_CPPFLAGS = \ -DSYSCONFDIR='"$(sysconfdir)"' \ -Wall \ $(SQLITE3_CFLAGS) LDADD = \ libdiag.a \ $(READLINE_LIBS) \ $(CURSES_LIB) \ $(SQLITE3_LIBS) \ -lpcrecpp dist_noinst_DATA = \ default-log-formats.json \ dump-pid.sh noinst_HEADERS = \ ansi_scrubber.hh \ auto_fd.hh \ auto_mem.hh \ auto_pid.hh \ bookmarks.hh \ bottom_status_source.hh \ byte_array.hh \ column_namer.hh \ data_scanner.hh \ data_parser.hh \ default-log-formats-json.hh \ db_sub_source.hh \ format-text-files.hh \ grapher.hh \ grep_highlighter.hh \ grep_proc.hh \ help.hh \ help.txt \ hist_source.hh \ init.sql \ init-sql.hh \ k_merge_tree.h \ line_buffer.hh \ listview_curses.hh \ lnav.hh \ lnav_commands.hh \ lnav_config.hh \ lnav_log.hh \ lnav_util.hh \ log_accel.hh \ log_data_helper.hh \ log_data_table.hh \ log_format.hh \ log_format_loader.hh \ logfile.hh \ logfile_sub_source.hh \ pcrepp.hh \ piper_proc.hh \ ptimec.hh \ readline_curses.hh \ readline_highlighters.hh \ sequence_matcher.hh \ sequence_sink.hh \ session_data.hh \ shared_buffer.hh \ sql_util.hh \ sqlite-extension-func.h \ status_controllers.hh \ statusview_curses.hh \ strnatcmp.h \ strong_int.hh \ termios_guard.hh \ term_extra.hh \ textfile_sub_source.hh \ textview_curses.hh \ time_T.hh \ top_status_source.hh \ view_curses.hh \ vt52_curses.hh \ log_vtab_impl.hh \ log_format_impls.cc \ xterm_mouse.hh \ yajlpp.hh \ yajl/api/yajl_common.h \ yajl/api/yajl_gen.h \ yajl/api/yajl_parse.h \ yajl/api/yajl_tree.h \ yajl/yajl_alloc.h \ yajl/yajl_buf.h \ yajl/yajl_bytestack.h \ yajl/yajl_common.h \ yajl/yajl_encode.h \ yajl/yajl_lex.h \ yajl/yajl_parser.h \ yajl/yajl_version.h \ spookyhash/SpookyV2.h libdiag_a_SOURCES = \ ansi_scrubber.cc \ bookmarks.cc \ collation-functions.cc \ db_sub_source.cc \ extension-functions.c \ fs-extension-functions.cc \ grep_proc.cc \ hist_source.cc \ line_buffer.cc \ listview_curses.cc \ lnav_commands.cc \ lnav_config.cc \ lnav_log.cc \ lnav_util.cc \ log_accel.cc \ log_format.cc \ log_format_loader.cc \ logfile.cc \ logfile_sub_source.cc \ network-extension-functions.cc \ data_scanner.cc \ data_parser.cc \ ptimec_rt.cc \ readline_curses.cc \ readline_highlighters.cc \ session_data.cc \ sequence_matcher.cc \ shared_buffer.cc \ sqlite-extension-func.c \ statusview_curses.cc \ string-extension-functions.cc \ pcrepp.cc \ piper_proc.cc \ sql_util.cc \ state-extension-functions.cc \ strnatcmp.c \ textview_curses.cc \ time_fmts.cc \ view_curses.cc \ vt52_curses.cc \ log_vtab_impl.cc \ xterm_mouse.cc \ yajlpp.cc \ yajl/yajl.c \ yajl/yajl_alloc.c \ yajl/yajl_alloc.h \ yajl/yajl_buf.c \ yajl/yajl_buf.h \ yajl/yajl_bytestack.h \ yajl/yajl_encode.c \ yajl/yajl_encode.h \ yajl/yajl_gen.c \ yajl/yajl_lex.c \ yajl/yajl_lex.h \ yajl/yajl_parser.c \ yajl/yajl_parser.h \ yajl/yajl_tree.c \ yajl/yajl_version.c \ spookyhash/SpookyV2.cpp dist_noinst_SCRIPTS = \ init_sql.py TEXT2C_FILES = \ dump-pid-sh.o \ help.o \ init-sql.o \ default-log-formats-json.o lnav_SOURCES = lnav.cc $(HELP_SRC) lnav_LDADD = \ $(TEXT2C_FILES) \ $(LDADD) lnav_test_SOURCES = lnav.cc $(HELP_SRC) test_override.cc lnav_test_LDADD = \ $(TEXT2C_FILES) \ $(LDADD) bin2c_SOURCES = bin2c.c bin2c_LDADD = ptimec_SOURCES = ptimec.cc ptimec_LDADD = DISTCLEANFILES = \ dump-pid-sh.c \ help.c \ init-sql.c \ default-log-formats-json.c \ time_fmts.cc all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .cc .cpp .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign 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: $(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): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status src/config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) yajl/$(am__dirstamp): @$(MKDIR_P) yajl @: > yajl/$(am__dirstamp) yajl/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) yajl/$(DEPDIR) @: > yajl/$(DEPDIR)/$(am__dirstamp) yajl/yajl.$(OBJEXT): yajl/$(am__dirstamp) \ yajl/$(DEPDIR)/$(am__dirstamp) yajl/yajl_alloc.$(OBJEXT): yajl/$(am__dirstamp) \ yajl/$(DEPDIR)/$(am__dirstamp) yajl/yajl_buf.$(OBJEXT): yajl/$(am__dirstamp) \ yajl/$(DEPDIR)/$(am__dirstamp) yajl/yajl_encode.$(OBJEXT): yajl/$(am__dirstamp) \ yajl/$(DEPDIR)/$(am__dirstamp) yajl/yajl_gen.$(OBJEXT): yajl/$(am__dirstamp) \ yajl/$(DEPDIR)/$(am__dirstamp) yajl/yajl_lex.$(OBJEXT): yajl/$(am__dirstamp) \ yajl/$(DEPDIR)/$(am__dirstamp) yajl/yajl_parser.$(OBJEXT): yajl/$(am__dirstamp) \ yajl/$(DEPDIR)/$(am__dirstamp) yajl/yajl_tree.$(OBJEXT): yajl/$(am__dirstamp) \ yajl/$(DEPDIR)/$(am__dirstamp) yajl/yajl_version.$(OBJEXT): yajl/$(am__dirstamp) \ yajl/$(DEPDIR)/$(am__dirstamp) spookyhash/$(am__dirstamp): @$(MKDIR_P) spookyhash @: > spookyhash/$(am__dirstamp) spookyhash/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) spookyhash/$(DEPDIR) @: > spookyhash/$(DEPDIR)/$(am__dirstamp) spookyhash/SpookyV2.$(OBJEXT): spookyhash/$(am__dirstamp) \ spookyhash/$(DEPDIR)/$(am__dirstamp) libdiag.a: $(libdiag_a_OBJECTS) $(libdiag_a_DEPENDENCIES) $(EXTRA_libdiag_a_DEPENDENCIES) $(AM_V_at)-rm -f libdiag.a $(AM_V_AR)$(libdiag_a_AR) libdiag.a $(libdiag_a_OBJECTS) $(libdiag_a_LIBADD) $(AM_V_at)$(RANLIB) libdiag.a install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do 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) clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) bin2c$(EXEEXT): $(bin2c_OBJECTS) $(bin2c_DEPENDENCIES) $(EXTRA_bin2c_DEPENDENCIES) @rm -f bin2c$(EXEEXT) $(AM_V_CCLD)$(LINK) $(bin2c_OBJECTS) $(bin2c_LDADD) $(LIBS) lnav$(EXEEXT): $(lnav_OBJECTS) $(lnav_DEPENDENCIES) $(EXTRA_lnav_DEPENDENCIES) @rm -f lnav$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(lnav_OBJECTS) $(lnav_LDADD) $(LIBS) lnav-test$(EXEEXT): $(lnav_test_OBJECTS) $(lnav_test_DEPENDENCIES) $(EXTRA_lnav_test_DEPENDENCIES) @rm -f lnav-test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(lnav_test_OBJECTS) $(lnav_test_LDADD) $(LIBS) ptimec$(EXEEXT): $(ptimec_OBJECTS) $(ptimec_DEPENDENCIES) $(EXTRA_ptimec_DEPENDENCIES) @rm -f ptimec$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(ptimec_OBJECTS) $(ptimec_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f spookyhash/*.$(OBJEXT) -rm -f yajl/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ansi_scrubber.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bin2c.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bookmarks.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/collation-functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data_parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data_scanner.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/db_sub_source.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extension-functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs-extension-functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/grep_proc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hist_source.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/line_buffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listview_curses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lnav.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lnav_commands.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lnav_config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lnav_log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lnav_util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_accel.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_format.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_format_loader.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_vtab_impl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logfile_sub_source.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/network-extension-functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcrepp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/piper_proc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptimec.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptimec_rt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readline_curses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readline_highlighters.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sequence_matcher.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session_data.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/shared_buffer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sql_util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sqlite-extension-func.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/state-extension-functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statusview_curses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string-extension-functions.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strnatcmp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_override.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textview_curses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_fmts.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/view_curses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vt52_curses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xterm_mouse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yajlpp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@spookyhash/$(DEPDIR)/SpookyV2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@yajl/$(DEPDIR)/yajl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@yajl/$(DEPDIR)/yajl_alloc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@yajl/$(DEPDIR)/yajl_buf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@yajl/$(DEPDIR)/yajl_encode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@yajl/$(DEPDIR)/yajl_gen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@yajl/$(DEPDIR)/yajl_lex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@yajl/$(DEPDIR)/yajl_parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@yajl/$(DEPDIR)/yajl_tree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@yajl/$(DEPDIR)/yajl_version.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @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) $(PROGRAMS) $(SCRIPTS) $(DATA) \ $(HEADERS) config.h 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f spookyhash/$(DEPDIR)/$(am__dirstamp) -rm -f spookyhash/$(am__dirstamp) -rm -f yajl/$(DEPDIR)/$(am__dirstamp) -rm -f yajl/$(am__dirstamp) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \ clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) spookyhash/$(DEPDIR) yajl/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr 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) spookyhash/$(DEPDIR) yajl/$(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: all install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic clean-noinstLIBRARIES \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-hdr \ 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 tags-am uninstall \ uninstall-am uninstall-binPROGRAMS help.c: $(srcdir)/help.txt bin2c ./bin2c -z -c $(srcdir)/help.txt $@ dump-pid-sh.c: $(srcdir)/dump-pid.sh bin2c ./bin2c -z -c $(srcdir)/dump-pid.sh $@ default-log-formats-json.c: $(srcdir)/default-log-formats.json bin2c ./bin2c -z -c $(srcdir)/default-log-formats.json $@ init.sql: $(srcdir)/init_sql.py $(PYTHON) $(srcdir)/init_sql.py > $@ init-sql.c: $(srcdir)/init.sql bin2c ./bin2c -z -c $(srcdir)/init.sql $@ time_fmts.cc: ptimec ./ptimec $(TIME_FORMATS) > $@ uncrusty: (cd $(srcdir) && uncrustify -c ../lnav.cfg --replace $(SOURCES) \ $(HEADERS)) # 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: lnav-0.7.0/src/network-extension-functions.cc000664 000765 000024 00000011446 12211635054 021544 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file nextwork-extension-functions.cc */ #include #include #include #include #include #include #include #include #include #include "sqlite3.h" #include "sqlite-extension-func.h" static void sql_gethostbyname(sqlite3_context *context, int argc, sqlite3_value **argv) { char buffer[INET6_ADDRSTRLEN]; const char * name_in; struct addrinfo *ai; void * addr_ptr = NULL; int rc; assert(argc >= 1 && argc <= 2); if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { sqlite3_result_null(context); return; } name_in = (const char *)sqlite3_value_text(argv[0]); while ((rc = getaddrinfo(name_in, NULL, NULL, &ai)) == EAI_AGAIN) { sqlite3_sleep(10); } if (rc != 0) { sqlite3_result_text(context, name_in, -1, SQLITE_TRANSIENT); return; } switch (ai->ai_family) { case AF_INET: addr_ptr = &((struct sockaddr_in *)ai->ai_addr)->sin_addr; break; case AF_INET6: addr_ptr = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; break; } inet_ntop(ai->ai_family, addr_ptr, buffer, sizeof(buffer)); sqlite3_result_text(context, buffer, -1, SQLITE_TRANSIENT); freeaddrinfo(ai); } static void sql_gethostbyaddr(sqlite3_context *context, int argc, sqlite3_value **argv) { union { struct sockaddr_in sin; struct sockaddr_in6 sin6; } sa; const char *addr_str; char buffer[NI_MAXHOST]; int family, socklen; char * addr_raw; int rc; assert(argc == 1); if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { sqlite3_result_null(context); return; } addr_str = (const char *)sqlite3_value_text(argv[0]); memset(&sa, 0, sizeof(sa)); if (strchr(addr_str, ':')) { family = AF_INET6; socklen = sizeof(struct sockaddr_in6); sa.sin6.sin6_family = family; addr_raw = (char *)&sa.sin6.sin6_addr; } else { family = AF_INET; socklen = sizeof(struct sockaddr_in); sa.sin.sin_family = family; addr_raw = (char *)&sa.sin.sin_addr; } if (inet_pton(family, addr_str, addr_raw) != 1) { sqlite3_result_text(context, addr_str, -1, SQLITE_TRANSIENT); return; } while ((rc = getnameinfo((struct sockaddr *)&sa, socklen, buffer, sizeof(buffer), NULL, 0, 0)) == EAI_AGAIN) { sqlite3_sleep(10); } if (rc != 0) { sqlite3_result_text(context, addr_str, -1, SQLITE_TRANSIENT); return; } sqlite3_result_text(context, buffer, -1, SQLITE_TRANSIENT); } int network_extension_functions(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs) { static const struct FuncDef network_funcs[] = { { "gethostbyname", 1, 0, SQLITE_UTF8, 0, sql_gethostbyname }, { "gethostbyaddr", 1, 0, SQLITE_UTF8, 0, sql_gethostbyaddr }, { NULL } }; *basic_funcs = network_funcs; return SQLITE_OK; } lnav-0.7.0/src/pcrepp.cc000664 000765 000024 00000004551 12305367255 015334 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file pcrepp.cc */ #include "config.h" #include #include "pcrepp.hh" const int JIT_STACK_MIN_SIZE = 32 * 1024; const int JIT_STACK_MAX_SIZE = 512 * 1024; pcre_context::capture_t *pcre_context::operator[](const char *name) const { capture_t *retval = NULL; int index; index = this->pc_pcre->name_index(name); if (index != PCRE_ERROR_NOSUBSTRING) { retval = &this->pc_captures[index + 1]; } return retval; } #ifdef PCRE_STUDY_JIT_COMPILE pcre_jit_stack *pcrepp::jit_stack(void) { static pcre_jit_stack *retval = NULL; if (retval == NULL) { retval = pcre_jit_stack_alloc(JIT_STACK_MIN_SIZE, JIT_STACK_MAX_SIZE); } return retval; } #else #warning "pcrejit is not available, search performance will be degraded" void pcrepp::pcre_free_study(pcre_extra *extra) { free(extra); } #endif lnav-0.7.0/src/pcrepp.hh000664 000765 000024 00000033457 12313321320 015333 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file pcrepp.hh * * A C++ adapter for the pcre library. The interface provided here has a * different focus than the pcrecpp.h file included in the pcre distribution. * The standard pcrecpp.h interface is more concerned with regular expressions * that are digesting data to be used within the program itself. Whereas this * interface is dealing with regular expression entered by the user and * processing a series of matches on text files. */ #ifndef __pcrepp_hh #define __pcrepp_hh #ifdef HAVE_PCRE_H #include #elif HAVE_PCRE_PCRE_H #include #else #error "pcre.h not found?" #endif #include #include #include #include #include "lnav_log.hh" #include "auto_mem.hh" #include class pcrepp; /** * Context that tracks captures found during a match operation. This class is a * base that defines iterator methods and fields, but does not allocate space * for the capture array. */ class pcre_context { public: typedef struct capture { capture() { /* We don't initialize anything since it's a perf hit. */ }; capture(int begin, int end) : c_begin(begin), c_end(end) { require(begin <= end); }; int c_begin; int c_end; bool is_valid() const { return this->c_begin != -1; }; int length() const { return this->c_end - this->c_begin; }; } capture_t; typedef capture_t *iterator; typedef const capture_t *const_iterator; /** @return The maximum number of strings this context can capture. */ int get_max_count() const { return this->pc_max_count; }; void set_count(int count) { this->pc_count = count; }; int get_count(void) const { return this->pc_count; }; void set_pcrepp(const pcrepp *src) { this->pc_pcre = src; }; /** * @return a capture_t that covers all of the text that was matched. */ capture_t *all() { return pc_captures; }; /** @return An iterator to the first capture. */ iterator begin() { return pc_captures + 1; }; /** @return An iterator that refers to the end of the capture array. */ iterator end() { return pc_captures + pc_count; }; capture_t *operator[](int offset) { if (offset < 0) { return NULL; } return &this->pc_captures[offset + 1]; }; capture_t *operator[](const char *name) const; capture_t *operator[](const std::string &name) const { return (*this)[name.c_str()]; }; capture_t *first_valid(void) const { for (int lpc = 1; lpc < this->pc_count; lpc++) { if (this->pc_captures[lpc].is_valid()) { return &this->pc_captures[lpc]; } } return NULL; }; protected: pcre_context(capture_t *captures, int max_count) : pc_pcre(NULL), pc_captures(captures), pc_max_count(max_count), pc_count(0) { }; const pcrepp *pc_pcre; capture_t *pc_captures; int pc_max_count; int pc_count; }; struct capture_if_not { capture_if_not(int begin) : cin_begin(begin) { }; bool operator()(const pcre_context::capture_t &cap) const { return cap.c_begin != this->cin_begin; } int cin_begin; }; inline pcre_context::iterator skip_invalid_captures(pcre_context::iterator iter, pcre_context::iterator pc_end) { for (; iter != pc_end; ++iter) { if (iter->c_begin == -1) { continue; } } return iter; } /** * A pcre_context that allocates storage for the capture array within the object * itself. */ template class pcre_context_static : public pcre_context { public: pcre_context_static() : pcre_context(this->pc_match_buffer, MAX_COUNT + 1) { }; private: capture_t pc_match_buffer[MAX_COUNT + 1]; }; /** * */ class pcre_input { public: pcre_input(const char *str, size_t off = 0, size_t len = -1) : pi_offset(off), pi_next_offset(off), pi_length(len), pi_string(str) { if (this->pi_length == (size_t)-1) { this->pi_length = strlen(str); } }; pcre_input(const std::string &str, size_t off = 0) : pi_offset(off), pi_next_offset(off), pi_length(str.length()), pi_string(str.c_str()) {}; const char *get_string() const { return this->pi_string; }; const char *get_substr_start(pcre_context::const_iterator iter) const { return &this->pi_string[iter->c_begin]; }; std::string get_substr(pcre_context::const_iterator iter) const { if (iter->c_begin == -1) { return ""; } return std::string(&this->pi_string[iter->c_begin], iter->length()); }; void get_substr(pcre_context::const_iterator iter, char *dst) const { memcpy(dst, &this->pi_string[iter->c_begin], iter->length()); dst[iter->length()] = '\0'; }; void reset(const char *str, size_t off = 0, size_t len = -1) { this->pi_string = str; this->pi_offset = off; this->pi_next_offset = off; if (this->pi_length == (size_t)-1) { this->pi_length = strlen(str); } else { this->pi_length = len; } } void reset(const std::string &str, size_t off = 0) { this->reset(str.c_str(), off, str.length()); }; size_t pi_offset; size_t pi_next_offset; size_t pi_length; private: const char *pi_string; }; struct pcre_named_capture { class iterator { public: iterator(pcre_named_capture *pnc, size_t name_len) : i_named_capture(pnc), i_name_len(name_len) { }; iterator() : i_named_capture(NULL), i_name_len(0) { }; const pcre_named_capture &operator*(void) const { return *this->i_named_capture; }; const pcre_named_capture *operator->(void) const { return this->i_named_capture; }; bool operator!=(const iterator &rhs) const { return this->i_named_capture != rhs.i_named_capture; }; iterator &operator++() { char *ptr = (char *)this->i_named_capture; ptr += this->i_name_len; this->i_named_capture = (pcre_named_capture *)ptr; return *this; }; private: pcre_named_capture *i_named_capture; size_t i_name_len; }; int index() const { return (this->pnc_index_msb << 8 | this->pnc_index_lsb) - 1; }; char pnc_index_msb; char pnc_index_lsb; char pnc_name[]; }; class pcrepp { public: class error : public std::exception { public: error(std::string msg, int offset) : e_msg(msg), e_offset(offset) { }; virtual ~error() throw () { }; virtual const char *what() const throw() { return this->e_msg.c_str(); }; const std::string e_msg; int e_offset; }; pcrepp(pcre *code) : p_code(code), p_code_extra(pcre_free_study) { pcre_refcount(this->p_code, 1); this->study(); }; pcrepp(const char *pattern, int options = 0) : p_code_extra(pcre_free_study) { const char *errptr; int eoff; if ((this->p_code = pcre_compile(pattern, options, &errptr, &eoff, NULL)) == NULL) { throw error(errptr, eoff); } pcre_refcount(this->p_code, 1); this->study(); }; pcrepp(const pcrepp &other) { this->p_code = other.p_code; pcre_refcount(this->p_code, 1); this->study(); }; virtual ~pcrepp() { if (pcre_refcount(this->p_code, -1) == 0) { free(this->p_code); this->p_code = 0; } }; pcre_named_capture::iterator named_begin() const { return pcre_named_capture::iterator(this->p_named_entries, this->p_name_len); }; pcre_named_capture::iterator named_end() const { char *ptr = (char *)this->p_named_entries; ptr += this->p_named_count * this->p_name_len; return pcre_named_capture::iterator((pcre_named_capture *)ptr, this->p_name_len); }; int name_index(const std::string &name) const { return this->name_index(name.c_str()); }; int name_index(const char *name) const { int retval = pcre_get_stringnumber(this->p_code, name); if (retval == PCRE_ERROR_NOSUBSTRING) return retval; return retval - 1; }; bool match(pcre_context &pc, pcre_input &pi, int options = 0) const { int length, startoffset, filtered_options = options; int count = pc.get_max_count(); const char *str; int rc; pc.set_pcrepp(this); pi.pi_offset = pi.pi_next_offset; str = pi.get_string(); if (filtered_options & PCRE_ANCHORED) { filtered_options &= ~PCRE_ANCHORED; str = &str[pi.pi_offset]; startoffset = 0; length = pi.pi_length - pi.pi_offset; } else { startoffset = pi.pi_offset; length = pi.pi_length; } rc = pcre_exec(this->p_code, this->p_code_extra.in(), str, length, startoffset, filtered_options, (int *)pc.all(), count * 2); if (rc < 0) { switch (rc) { case PCRE_ERROR_NOMATCH: break; case PCRE_ERROR_PARTIAL: pc.set_count(1); return true; default: log_error("pcre err %d", rc); break; } } else if (rc == 0) { rc = 0; } else if (pc.all()->c_begin == pc.all()->c_end) { rc = 0; } else { if (options & PCRE_ANCHORED) { for (int lpc = 0; lpc < rc; lpc++) { if (pc.all()[lpc].c_begin == -1) { continue; } pc.all()[lpc].c_begin += pi.pi_offset; pc.all()[lpc].c_end += pi.pi_offset; } } pi.pi_next_offset = pc.all()->c_end; } pc.set_count(rc); return rc > 0; }; #ifdef PCRE_STUDY_JIT_COMPILE static pcre_jit_stack *jit_stack(void); #else static void pcre_free_study(pcre_extra *); #endif private: void study(void) { const char *errptr; this->p_code_extra = pcre_study(this->p_code, #ifdef PCRE_STUDY_JIT_COMPILE PCRE_STUDY_JIT_COMPILE, #else 0, #endif &errptr); if (!this->p_code_extra && errptr) { log_error("pcre_study error: %s", errptr); } if (this->p_code_extra != NULL) { pcre_extra *extra = this->p_code_extra; extra->flags |= (PCRE_EXTRA_MATCH_LIMIT | PCRE_EXTRA_MATCH_LIMIT_RECURSION); extra->match_limit = 10000; extra->match_limit_recursion = 500; #ifdef PCRE_STUDY_JIT_COMPILE pcre_assign_jit_stack(extra, NULL, jit_stack()); #endif } pcre_fullinfo(this->p_code, this->p_code_extra, PCRE_INFO_NAMECOUNT, &this->p_named_count); pcre_fullinfo(this->p_code, this->p_code_extra, PCRE_INFO_NAMEENTRYSIZE, &this->p_name_len); pcre_fullinfo(this->p_code, this->p_code_extra, PCRE_INFO_NAMETABLE, &this->p_named_entries); }; pcre *p_code; auto_mem p_code_extra; int p_named_count; int p_name_len; pcre_named_capture *p_named_entries; }; #endif lnav-0.7.0/src/piper_proc.cc000664 000765 000024 00000014023 12311035743 016167 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file piper_proc.cc */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "lnav_log.hh" #include "piper_proc.hh" #include "line_buffer.hh" using namespace std; static const char *STDIN_EOF_MSG = "---- END-OF-STDIN ----"; static int write_timestamp(int fd, off_t woff) { char time_str[64]; struct timeval tv; char ms_str[8]; gettimeofday(&tv, NULL); strftime(time_str, sizeof(time_str), "%FT%T", localtime(&tv.tv_sec)); snprintf(ms_str, sizeof(ms_str), ".%03d", (int)(tv.tv_usec / 1000)); strcat(time_str, ms_str); strcat(time_str, " "); return pwrite(fd, time_str, strlen(time_str), woff); } piper_proc::piper_proc(int pipefd, bool timestamp, const char *filename) : pp_fd(-1), pp_child(-1) { require(pipefd >= 0); if (filename) { if ((this->pp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0600)) == -1) { perror("Unable to open output file for stdin"); throw error(errno); } } else { char piper_tmpname[PATH_MAX]; const char *tmpdir; if ((tmpdir = getenv("TMPDIR")) == NULL) { tmpdir = _PATH_VARTMP; } snprintf(piper_tmpname, sizeof(piper_tmpname), "%s/lnav.piper.XXXXXX", tmpdir); if ((this->pp_fd = mkstemp(piper_tmpname)) == -1) { throw error(errno); } unlink(piper_tmpname); } fcntl(this->pp_fd, F_SETFD, FD_CLOEXEC); this->pp_child = fork(); switch (this->pp_child) { case -1: throw error(errno); case 0: { auto_fd infd(pipefd); line_buffer lb; off_t woff = 0, last_woff = 0; off_t off = 0, last_off = 0; int nullfd; nullfd = open("/dev/null", O_RDWR); dup2(nullfd, STDOUT_FILENO); fcntl(infd.get(), F_SETFL, O_NONBLOCK); lb.set_fd(infd); do { line_value lv; fd_set rready; FD_ZERO(&rready); FD_SET(lb.get_fd(), &rready); select(lb.get_fd() + 1, &rready, NULL, NULL, NULL); last_off = off; while (lb.read_line(off, lv, true)) { int wrc; last_woff = woff; if (timestamp) { wrc = write_timestamp(this->pp_fd, woff); if (wrc == -1) { perror("Unable to write to output file for stdin"); break; } woff += wrc; } /* Need to do pwrite here since the fd is used by the main * lnav process as well. */ wrc = pwrite(this->pp_fd, lv.lv_start, lv.lv_len, woff); if (wrc == -1) { perror("Unable to write to output file for stdin"); break; } woff += wrc; if (lv.lv_start[lv.lv_len - 1] != '\n') { off = last_off; woff = last_woff; } last_off = off; } } while (lb.get_file_size() == (ssize_t)-1); if (timestamp) { int wrc; wrc = write_timestamp(this->pp_fd, woff); if (wrc == -1) { perror("Unable to write to output file for stdin"); break; } woff += wrc; wrc = pwrite(this->pp_fd, STDIN_EOF_MSG, strlen(STDIN_EOF_MSG), woff); if (wrc == -1) { perror("Unable to write to output file for stdin"); break; } } } _exit(0); break; default: break; } } bool piper_proc::has_exited() { if (this->pp_child > 0) { int rc, status; rc = waitpid(this->pp_child, &status, WNOHANG); if (rc == -1 || rc == 0) { return false; } this->pp_child = -1; } return true; } piper_proc::~piper_proc() { if (this->pp_child > 0) { int status; kill(this->pp_child, SIGTERM); while (waitpid(this->pp_child, &status, 0) < 0 && (errno == EINTR)) { ; } this->pp_child = -1; } } lnav-0.7.0/src/piper_proc.hh000664 000765 000024 00000005533 12231751727 016217 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file piper_proc.hh */ #ifndef __piper_proc_hh #define __piper_proc_hh #include #include /** * Creates a subprocess that reads data from a pipe and writes it to a file so * lnav can treat it like any other file and do preads. * * TODO: Add support for gzipped files. */ class piper_proc { public: class error : public std::exception { public: error(int err) : e_err(err) { }; int e_err; }; /** * Forks a subprocess that will read data from the given file descriptor * and write it to a temporary file. * * @param pipefd The file descriptor to read the file contents from. * @param timestamp True if an ISO 8601 timestamp should be prepended onto * the lines read from pipefd. * @param filename The name of the file to save the input to, otherwise a * temporary file will be created. */ piper_proc(int pipefd, bool timestamp, const char *filename = NULL); bool has_exited(); /** * Terminates the child process. */ virtual ~piper_proc(); /** @return The file descriptor for the temporary file. */ int get_fd() const { return this->pp_fd; }; private: /** A file descriptor that refers to the temporary file. */ int pp_fd; /** The child process' pid. */ pid_t pp_child; }; #endif lnav-0.7.0/src/ptimec.cc000664 000765 000024 00000006737 12313316216 015322 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file ptimec.cc */ #include #include #include const char *PRELUDE = "\ #include \n\ #include \n\ #include \"ptimec.hh\"\n\ \n\ "; char *escape_char(char ch) { static char charstr[4]; if (ch == '\'') { strcpy(charstr, "\\'"); } else { charstr[0] = ch; charstr[1] = '\0'; } return charstr; } int main(int argc, char *argv[]) { int retval = EXIT_SUCCESS; for (int lpc = 1; lpc < argc; lpc++) { const char *arg = argv[lpc]; fputs(PRELUDE, stdout); printf("bool ptime_f%d(struct tm *dst, const char *str, off_t &off, size_t len) {\n", lpc); for (int index = 0; arg[index]; arg++) { if (arg[index] == '%') { switch (arg[index + 1]) { case 'a': case 'Z': printf(" if (!ptime_upto('%s', str, off, len)) return false;\n", escape_char(arg[index + 2])); arg += 1; break; default: printf(" if (!ptime_%c(dst, str, off, len)) return false;\n", arg[index + 1]); arg += 1; break; } } else { printf(" if (!ptime_char('%s', str, off, len)) return false;\n", escape_char(arg[index])); } } printf(" return true;\n"); printf("}\n\n"); } printf("struct ptime_fmt PTIMEC_FORMATS[] = {\n"); for (int lpc = 1; lpc < argc; lpc++) { printf(" { \"%s\", ptime_f%d },\n", argv[lpc], lpc); } printf("\n"); printf(" { NULL, NULL }\n"); printf("};\n"); printf("const char *PTIMEC_FORMAT_STR[] = {\n"); for (int lpc = 1; lpc < argc; lpc++) { printf(" \"%s\",\n", argv[lpc]); } printf("\n"); printf(" NULL\n"); printf("};\n"); return retval; } lnav-0.7.0/src/ptimec.hh000664 000765 000024 00000016326 12315713704 015334 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file ptimec.hh */ #ifndef __pctimec_hh #define __pctimec_hh // XXX #include #include #include #include #define PTIME_CONSUME(amount, block) \ if (off_inout + amount > len) { \ return false; \ } \ \ block \ \ off_inout += amount; #define ABR_TO_INT(a, b, c) \ ((a) | (b << 8) | (c << 16)) inline bool ptime_upto(char ch, const char *str, off_t &off_inout, size_t len) { for (; off_inout < len; off_inout++) { if (str[off_inout] == ch) { return true; } } return false; } bool ptime_b_slow(struct tm *dst, const char *str, off_t &off_inout, size_t len); inline bool ptime_b(struct tm *dst, const char *str, off_t &off_inout, size_t len) { if (off_inout + 3 < len) { int *iptr = (int *)(&str[off_inout]); int val; switch (*iptr & 0xdfdfdf) { case ABR_TO_INT('J', 'A', 'N'): val = 0; break; case ABR_TO_INT('F', 'E', 'B'): val = 1; break; case ABR_TO_INT('M', 'A', 'R'): val = 2; break; case ABR_TO_INT('A', 'P', 'R'): val = 3; break; case ABR_TO_INT('M', 'A', 'Y'): val = 4; break; case ABR_TO_INT('J', 'U', 'N'): val = 5; break; case ABR_TO_INT('J', 'U', 'L'): val = 6; break; case ABR_TO_INT('A', 'U', 'G'): val = 7; break; case ABR_TO_INT('S', 'E', 'P'): val = 8; break; case ABR_TO_INT('O', 'C', 'T'): val = 9; break; case ABR_TO_INT('N', 'O', 'V'): val = 10; break; case ABR_TO_INT('D', 'E', 'C'): val = 11; break; default: val = -1; break; } if (val >= 0) { off_inout += 3; dst->tm_mon = val; return true; } } return ptime_b_slow(dst, str, off_inout, len); } inline bool ptime_S(struct tm *dst, const char *str, off_t &off_inout, size_t len) { PTIME_CONSUME(2, { if (str[off_inout + 1] > '9') { return false; } dst->tm_sec = (str[off_inout] - '0') * 10 + (str[off_inout + 1] - '0'); }); return (dst->tm_sec >= 0 && dst->tm_sec <= 59); } inline bool ptime_M(struct tm *dst, const char *str, off_t &off_inout, size_t len) { PTIME_CONSUME(2, { if (str[off_inout + 1] > '9') { return false; } dst->tm_min = (str[off_inout] - '0') * 10 + (str[off_inout + 1] - '0'); }); return (dst->tm_min >= 0 && dst->tm_min <= 59); } inline bool ptime_H(struct tm *dst, const char *str, off_t &off_inout, size_t len) { PTIME_CONSUME(2, { if (str[off_inout + 1] > '9') { return false; } dst->tm_hour = (str[off_inout] - '0') * 10 + (str[off_inout + 1] - '0'); }); return (dst->tm_hour >= 0 && dst->tm_hour <= 23); } inline bool ptime_d(struct tm *dst, const char *str, off_t &off_inout, size_t len) { PTIME_CONSUME(2, { if (str[off_inout] == ' ') { dst->tm_mday = 0; } else { dst->tm_mday = (str[off_inout] - '0') * 10; } if (str[off_inout + 1] > '9') { return false; } dst->tm_mday += (str[off_inout + 1] - '0'); }); return (dst->tm_mday >= 1 && dst->tm_mday <= 31); } inline bool ptime_m(struct tm *dst, const char *str, off_t &off_inout, size_t len) { PTIME_CONSUME(2, { if (str[off_inout + 1] > '9') { return false; } dst->tm_mon = ((str[off_inout] - '0') * 10 + (str[off_inout + 1] - '0')) - 1; }); return (0 <= dst->tm_mon && dst->tm_mon <= 11); } inline bool ptime_Y(struct tm *dst, const char *str, off_t &off_inout, size_t len) { PTIME_CONSUME(4, { dst->tm_year = ( (str[off_inout + 0] - '0') * 1000 + (str[off_inout + 1] - '0') * 100 + (str[off_inout + 2] - '0') * 10 + (str[off_inout + 3] - '0') * 1) - 1900; }); return true; } inline bool ptime_y(struct tm *dst, const char *str, off_t &off_inout, size_t len) { PTIME_CONSUME(2, { dst->tm_year = ( (str[off_inout + 0] - '0') * 10 + (str[off_inout + 1] - '0') * 1); if (dst->tm_year >= 0 && dst->tm_year < 100) { if (dst->tm_year < 69) { dst->tm_year += 100; } return true; } }); return true; } inline bool ptime_z(struct tm *dst, const char *str, off_t &off_inout, size_t len) { #ifdef HAVE_STRUCT_TM_TM_ZONE PTIME_CONSUME(5, { long sign; long hours; long mins; if (str[off_inout] == '+') { sign = 1; } else if (str[off_inout] == '-') { sign = -1; } else { return false; } hours = ( (str[off_inout + 0] - '0') * 10 + (str[off_inout + 1] - '0') * 1) * 60 * 60; mins = ( (str[off_inout + 2] - '0') * 10 + (str[off_inout + 3] - '0') * 1) * 60; dst->tm_gmtoff = hours + mins; }); #endif return true; } inline bool ptime_char(char val, const char *str, off_t &off_inout, size_t len) { PTIME_CONSUME(1, { if (str[off_inout] != val) { return false; } }); return true; } typedef bool (*ptime_func)(struct tm *dst, const char *str, off_t &off, size_t len); struct ptime_fmt { const char *pf_fmt; ptime_func pf_func; }; extern struct ptime_fmt PTIMEC_FORMATS[]; extern const char *PTIMEC_FORMAT_STR[]; #endif lnav-0.7.0/src/ptimec_rt.cc000664 000765 000024 00000003645 12313213321 016013 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file ptimec_rt.cc */ #include "config.h" #include #include #include #include #include "ptimec.hh" bool ptime_b_slow(struct tm *dst, const char *str, off_t &off_inout, size_t len) { const char *end_of_date; if ((end_of_date = strptime(&str[off_inout], "%b", dst)) != NULL) { off_inout = end_of_date - str; return true; } return false; } lnav-0.7.0/src/readline_curses.cc000664 000765 000024 00000060526 12310250073 017177 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file readline_curses.cc */ #include "config.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_PTY_H #include #endif #ifdef HAVE_UTIL_H #include #endif #ifdef HAVE_LIBUTIL_H #include #endif #include #include "pcrepp.hh" #include "auto_mem.hh" #include "lnav_log.hh" #include "ansi_scrubber.hh" #include "readline_curses.hh" using namespace std; static int got_line = 0; static sig_atomic_t got_timeout = 0; static sig_atomic_t got_winch = 0; static readline_curses *child_this; static sig_atomic_t looping = 1; static const int HISTORY_SIZE = 256; static const char *RL_INIT[] = { /* * XXX Need to keep the input on a single line since the display screws * up if it wraps around. */ "set horizontal-scroll-mode on", NULL }; readline_context *readline_context::loaded_context; set * readline_context::arg_possibilities; static string last_match_str; static bool last_match_str_valid; static void sigalrm(int sig) { got_timeout = 1; } static void sigwinch(int sig) { got_winch = 1; } static void sigterm(int sig) { looping = 0; } static void line_ready_tramp(char *line) { child_this->line_ready(line); got_line = 1; rl_callback_handler_remove(); } static int sendall(int sock, const char *buf, size_t len) { off_t offset = 0; while (len > 0) { int rc = send(sock, &buf[offset], len, 0); if (rc == -1) { switch (errno) { case EAGAIN: case EINTR: break; default: return -1; } } else { len -= rc; offset += rc; } } return 0; } static int sendstring(int sock, const char *buf, size_t len) { if (sendall(sock, (char *)&len, sizeof(len)) == -1) { return -1; } else if (sendall(sock, buf, len) == -1) { return -1; } return 0; } static int recvall(int sock, char *buf, size_t len) { off_t offset = 0; while (len > 0) { int rc = recv(sock, &buf[offset], len, 0); if (rc == -1) { switch (errno) { case EAGAIN: case EINTR: break; default: return -1; } } else if (rc == 0) { errno = EIO; return -1; } else { len -= rc; offset += rc; } } return 0; } static ssize_t recvstring(int sock, char *buf, size_t len) { ssize_t retval; if (recvall(sock, (char *)&retval, sizeof(retval)) == -1) { return -1; } else if (retval > len) { return -1; } else if (recvall(sock, buf, retval) == -1) { return -1; } return retval; } char *readline_context::completion_generator(const char *text, int state) { static vector matches; char *retval = NULL; if (state == 0) { int len = strlen(text); matches.clear(); if (arg_possibilities != NULL) { set::iterator iter; for (iter = arg_possibilities->begin(); iter != arg_possibilities->end(); ++iter) { int (*cmpfunc)(const char *, const char *, size_t); cmpfunc = (loaded_context->is_case_sensitive() ? strncmp : strncasecmp); if (cmpfunc(text, iter->c_str(), len) == 0) { matches.push_back(*iter); } } } if (matches.size() == 1) { if (strcmp(text, matches[0].c_str()) == 0) { matches.pop_back(); } last_match_str_valid = false; if (sendstring(child_this->rc_command_pipe[readline_curses::RCF_SLAVE], "m:0:0", 5) == -1) { _exit(1); } } } if (!matches.empty()) { retval = strdup(matches.back().c_str()); matches.pop_back(); } return retval; } char **readline_context::attempted_completion(const char *text, int start, int end) { char **retval = NULL; if (loaded_context->rc_possibilities.find("*") != loaded_context->rc_possibilities.end()) { arg_possibilities = &loaded_context->rc_possibilities["*"]; rl_completion_append_character = loaded_context->rc_append_character; } else if (start == 0) { arg_possibilities = &loaded_context->rc_possibilities["__command"]; rl_completion_append_character = loaded_context->rc_append_character; } else { char * space; string cmd; rl_completion_append_character = 0; space = strchr(rl_line_buffer, ' '); require(space != NULL); cmd = string(rl_line_buffer, space - rl_line_buffer); vector &proto = loaded_context->rc_prototypes[cmd]; if (proto.empty()) { arg_possibilities = NULL; } else if (proto[0] == "filename") { return NULL; /* XXX */ } else { arg_possibilities = &(loaded_context->rc_possibilities[proto[0]]); } } retval = rl_completion_matches(text, completion_generator); if (retval == NULL) { rl_attempted_completion_over = 1; } return retval; } readline_curses::readline_curses() : rc_active_context(-1), rc_child(-1), rc_value_expiration(0), rc_matches_remaining(0), rc_max_match_length(0) { struct winsize ws; int sp[2]; log_info("readline: %s", rl_library_version); if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) { throw error(errno); } this->rc_command_pipe[RCF_MASTER] = sp[RCF_MASTER]; this->rc_command_pipe[RCF_SLAVE] = sp[RCF_SLAVE]; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1) { throw error(errno); } if (openpty(this->rc_pty[RCF_MASTER].out(), this->rc_pty[RCF_SLAVE].out(), NULL, NULL, &ws) < 0) { throw error(errno); } if ((this->rc_child = fork()) == -1) { throw error(errno); } if (this->rc_child == 0) { char buffer[1024]; this->rc_command_pipe[RCF_MASTER].reset(); this->rc_pty[RCF_MASTER].reset(); signal(SIGALRM, sigalrm); signal(SIGWINCH, sigwinch); signal(SIGINT, sigterm); signal(SIGTERM, sigterm); dup2(this->rc_pty[RCF_SLAVE], STDIN_FILENO); dup2(this->rc_pty[RCF_SLAVE], STDOUT_FILENO); setenv("TERM", "vt52", 1); rl_initialize(); using_history(); stifle_history(HISTORY_SIZE); for (int lpc = 0; RL_INIT[lpc]; lpc++) { strcpy(buffer, RL_INIT[lpc]); rl_parse_and_bind(buffer); /* NOTE: buffer is modified */ } child_this = this; } else { this->rc_command_pipe[RCF_SLAVE].reset(); this->rc_pty[RCF_SLAVE].reset(); } } readline_curses::~readline_curses() { if (this->rc_child == 0) { _exit(0); } else if (this->rc_child > 0) { int status; kill(this->rc_child, SIGTERM); this->rc_child = -1; while (wait(&status) < 0 && (errno == EINTR)) { ; } } } void readline_curses::store_matches( char **matches, int num_matches, int max_len) { char msg[64]; int rc; max_len = 0; for (int lpc = 0; lpc <= num_matches; lpc++) { max_len = max(max_len, (int)strlen(matches[lpc])); } if (last_match_str_valid && strcmp(last_match_str.c_str(), matches[0]) == 0) { if (sendstring(child_this->rc_command_pipe[RCF_SLAVE], "n", 1) == -1) { _exit(1); } } else { rc = snprintf(msg, sizeof(msg), "m:%d:%d", num_matches, max_len); if (sendstring(child_this->rc_command_pipe[RCF_SLAVE], msg, rc) == -1) { _exit(1); } for (int lpc = 1; lpc <= num_matches; lpc++) { if (sendstring(child_this->rc_command_pipe[RCF_SLAVE], matches[lpc], strlen(matches[lpc])) == -1) { _exit(1); } } last_match_str = matches[0]; last_match_str_valid = true; } } void readline_curses::start(void) { if (this->rc_child != 0) { return; } map::iterator current_context; fd_set rfds; int maxfd; require(!this->rc_contexts.empty()); rl_completer_word_break_characters = (char *)" \t\n"; /* XXX */ rl_completion_display_matches_hook = store_matches; current_context = this->rc_contexts.end(); FD_ZERO(&rfds); FD_SET(STDIN_FILENO, &rfds); FD_SET(this->rc_command_pipe[RCF_SLAVE], &rfds); maxfd = max(STDIN_FILENO, this->rc_command_pipe[RCF_SLAVE].get()); while (looping) { fd_set ready_rfds = rfds; int rc; rc = select(maxfd + 1, &ready_rfds, NULL, NULL, NULL); if (rc < 0) { switch (errno) { case EINTR: break; } } else { if (FD_ISSET(STDIN_FILENO, &ready_rfds)) { struct itimerval itv; if (current_context == this->rc_contexts.end()) { looping = false; break; } itv.it_value.tv_sec = 0; itv.it_value.tv_usec = KEY_TIMEOUT; itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); rl_callback_read_char(); if (RL_ISSTATE(RL_STATE_DONE) && !got_line) { got_line = 1; this->line_ready(""); rl_callback_handler_remove(); } } if (FD_ISSET(this->rc_command_pipe[RCF_SLAVE], &ready_rfds)) { char msg[1024 + 1]; if ((rc = recvstring(this->rc_command_pipe[RCF_SLAVE], msg, sizeof(msg) - 1)) < 0) { } else { int context, prompt_start = 0; char type[32]; msg[rc] = '\0'; if (sscanf(msg, "f:%d:%n", &context, &prompt_start) == 1 && prompt_start != 0 && (current_context = this->rc_contexts.find(context)) != this->rc_contexts.end()) { current_context->second->load(); rl_callback_handler_install(&msg[prompt_start], line_ready_tramp); last_match_str_valid = false; } else if (strcmp(msg, "a") == 0) { char reply[4]; rl_done = 1; got_timeout = 0; got_line = 1; rl_callback_handler_remove(); snprintf(reply, sizeof(reply), "a"); if (sendstring(this->rc_command_pipe[RCF_SLAVE], reply, strlen(reply)) == -1) { perror("abort: write failed"); _exit(1); } } else if (sscanf(msg, "ap:%d:%31[^:]:%n", &context, type, &prompt_start) == 2) { require(this->rc_contexts[context] != NULL); this->rc_contexts[context]-> add_possibility(string(type), string(&msg[prompt_start])); } else if (sscanf(msg, "rp:%d:%31[^:]:%n", &context, type, &prompt_start) == 2) { require(this->rc_contexts[context] != NULL); this->rc_contexts[context]-> rem_possibility(string(type), string(&msg[prompt_start])); } else if (sscanf(msg, "cp:%d:%s", &context, type)) { this->rc_contexts[context]->clear_possibilities(type); } else { log_error("unhandled message: %s", msg); } } } } if (got_timeout) { char msg[1024]; got_timeout = 0; snprintf(msg, sizeof(msg), "t:%s", rl_line_buffer); if (sendstring(this->rc_command_pipe[RCF_SLAVE], msg, strlen(msg)) == -1) { _exit(1); } } if (got_line) { struct itimerval itv; got_line = 0; itv.it_value.tv_sec = 0; itv.it_value.tv_usec = 0; itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; if (setitimer(ITIMER_REAL, &itv, NULL) < 0) { log_error("setitimer: %s", strerror(errno)); } current_context->second->save(); current_context = this->rc_contexts.end(); } if (got_winch) { struct winsize ws; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1) { throw error(errno); } got_winch = 0; rl_set_screen_size(ws.ws_row, ws.ws_col); } } std::map::iterator citer; for (citer = this->rc_contexts.begin(); citer != this->rc_contexts.end(); ++citer) { char *home; citer->second->load(); home = getenv("HOME"); if (home) { char hpath[2048]; snprintf(hpath, sizeof(hpath), "%s/.lnav/%s.history", home, citer->second->get_name().c_str()); write_history(hpath); } citer->second->save(); } _exit(0); } void readline_curses::line_ready(const char *line) { auto_mem expanded; char msg[1024]; int rc; rc = history_expand(rl_line_buffer, expanded.out()); switch (rc) { #if 0 /* TODO: fix clash between history and pcre metacharacters */ case -1: /* XXX */ snprintf(msg, sizeof(msg), "e:unable to expand history -- %s", expanded.in()); break; #endif case -1: snprintf(msg, sizeof(msg), "d:%s", line); break; case 0: case 1: case 2: /* XXX */ snprintf(msg, sizeof(msg), "d:%s", expanded.in()); break; } if (sendstring(this->rc_command_pipe[RCF_SLAVE], msg, strlen(msg)) == -1) { perror("line_ready: write failed"); _exit(1); } { HIST_ENTRY *entry; if (line[0] != '\0' && ( history_length == 0 || (entry = history_get(history_base + history_length - 1)) == NULL || strcmp(entry->line, line) != 0)) { add_history(line); } } } void readline_curses::check_fd_set(fd_set &ready_rfds) { int rc; if (FD_ISSET(this->rc_pty[RCF_MASTER], &ready_rfds)) { char buffer[128]; rc = read(this->rc_pty[RCF_MASTER], buffer, sizeof(buffer)); if (rc > 0) { this->map_output(buffer, rc); } } if (FD_ISSET(this->rc_command_pipe[RCF_MASTER], &ready_rfds)) { char msg[1024 + 1]; rc = recvstring(this->rc_command_pipe[RCF_MASTER], msg, sizeof(msg) - 1); if (rc >= 0) { string old_value = this->rc_value; msg[rc] = '\0'; if (this->rc_matches_remaining > 0) { this->rc_matches.push_back(msg); this->rc_matches_remaining -= 1; if (this->rc_matches_remaining == 0) { this->rc_display_match.invoke(this); } } else if (msg[0] == 'm') { if (sscanf(msg, "m:%d:%d", &this->rc_matches_remaining, &this->rc_max_match_length) != 2) { require(0); } this->rc_matches.clear(); if (this->rc_matches_remaining == 0) { this->rc_display_match.invoke(this); } } else { switch (msg[0]) { case 't': case 'd': this->rc_value = string(&msg[2]); break; } switch (msg[0]) { case 'a': require(rc == 1); this->rc_active_context = -1; this->vc_past_lines.clear(); this->rc_matches.clear(); this->rc_abort.invoke(this); this->rc_display_match.invoke(this); curs_set(0); break; case 't': if (this->rc_value != old_value) { this->rc_timeout.invoke(this); } break; case 'd': this->rc_active_context = -1; this->vc_past_lines.clear(); this->rc_matches.clear(); this->rc_perform.invoke(this); this->rc_display_match.invoke(this); curs_set(0); break; case 'n': this->rc_display_next.invoke(this); break; } } } } } void readline_curses::handle_key(int ch) { const char *bch; int len; bch = this->map_input(ch, len); if (write(this->rc_pty[RCF_MASTER], bch, len) == -1) { perror("handle_key: write failed"); } if (ch == '\t' || ch == '\r') { this->vc_past_lines.clear(); } } void readline_curses::focus(int context, const char *prompt) { char buffer[1024]; curs_set(1); this->rc_active_context = context; snprintf(buffer, sizeof(buffer), "f:%d:%s", context, prompt); if (sendstring(this->rc_command_pipe[RCF_MASTER], buffer, strlen(buffer) + 1) == -1) { perror("focus: write failed"); } wmove(this->vc_window, this->get_actual_y(), 0); wclrtoeol(this->vc_window); } void readline_curses::abort() { char buffer[1024]; snprintf(buffer, sizeof(buffer), "a"); if (sendstring(this->rc_command_pipe[RCF_MASTER], buffer, strlen(buffer)) == -1) { perror("abort: write failed"); } } void readline_curses::add_possibility(int context, const string &type, const string &value) { char buffer[1024]; if (value.empty()) { return; } snprintf(buffer, sizeof(buffer), "ap:%d:%s:%s", context, type.c_str(), value.c_str()); if (sendstring(this->rc_command_pipe[RCF_MASTER], buffer, strlen(buffer) + 1) == -1) { perror("add_possibility: write failed"); } } void readline_curses::rem_possibility(int context, const string &type, const string &value) { char buffer[1024]; snprintf(buffer, sizeof(buffer), "rp:%d:%s:%s", context, type.c_str(), value.c_str()); if (sendstring(this->rc_command_pipe[RCF_MASTER], buffer, strlen(buffer) + 1) == -1) { perror("rem_possiblity: write failed"); } } void readline_curses::clear_possibilities(int context, string type) { char buffer[1024]; snprintf(buffer, sizeof(buffer), "cp:%d:%s", context, type.c_str()); if (sendstring(this->rc_command_pipe[RCF_MASTER], buffer, strlen(buffer) + 1) == -1) { perror("clear_possiblity: write failed"); } } void readline_curses::do_update(void) { if (this->rc_active_context == -1) { int alt_start = -1; struct line_range lr(0, 0); attr_line_t al, alt_al; wmove(this->vc_window, this->get_actual_y(), 0); wclrtoeol(this->vc_window); if (time(NULL) > this->rc_value_expiration) { this->rc_value.clear(); } al.get_string() = this->rc_value; scrub_ansi_string(al.get_string(), al.get_attrs()); if (!this->rc_alt_value.empty()) { alt_al.get_string() = this->rc_alt_value; scrub_ansi_string(alt_al.get_string(), alt_al.get_attrs()); alt_start = getmaxx(this->vc_window) - alt_al.get_string().size(); } if (alt_start >= (int)(al.get_string().length() + 5)) { lr.lr_end = alt_al.get_string().length(); view_curses::mvwattrline(this->vc_window, this->get_actual_y(), alt_start, alt_al, lr); } lr.lr_end = al.get_string().length(); view_curses::mvwattrline(this->vc_window, this->get_actual_y(), 0, al, lr); this->set_x(0); } vt52_curses::do_update(); if (this->rc_active_context != -1) { readline_context *rc = this->rc_contexts[this->rc_active_context]; readline_highlighter_t hl = rc->get_highlighter(); if (hl != NULL) { char line[1024]; attr_line_t al; string &str = al.get_string(); int rc; rc = mvwinnstr(this->vc_window, this->get_actual_y(), 0, line, sizeof(line)); str = string(line, rc); hl(al, this->vc_x); view_curses::mvwattrline(this->vc_window, this->get_actual_y(), 0, al, line_range(0, rc)); wmove(this->vc_window, this->get_actual_y(), this->vc_x); } } } lnav-0.7.0/src/readline_curses.hh000664 000765 000024 00000022662 12307027320 017213 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file readline_curses.hh */ #ifndef __readline_curses_hh #define __readline_curses_hh #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "auto_fd.hh" #include "vt52_curses.hh" typedef void (*readline_highlighter_t)(attr_line_t &line, int x); /** * Container for information related to different readline contexts. Since * lnav uses readline for different inputs, we need a way to keep things like * history and tab-completions separate. */ class readline_context { public: typedef std::string (*command_t)(std::string cmdline, std::vector &args); typedef std::map command_map_t; readline_context(const std::string &name, command_map_t *commands = NULL, bool case_sensitive = true) : rc_name(name), rc_case_sensitive(case_sensitive), rc_highlighter(NULL) { char *home; if (commands != NULL) { command_map_t::iterator iter; for (iter = commands->begin(); iter != commands->end(); ++iter) { std::string cmd = iter->first; this->rc_possibilities["__command"].insert(cmd); iter->second(cmd, this->rc_prototypes[cmd]); } } memset(&this->rc_history, 0, sizeof(this->rc_history)); history_set_history_state(&this->rc_history); home = getenv("HOME"); if (home) { char hpath[2048]; snprintf(hpath, sizeof(hpath), "%s/.lnav/%s.history", home, this->rc_name.c_str()); read_history(hpath); this->save(); } this->rc_append_character = ' '; }; const std::string &get_name() const { return this->rc_name; }; void load(void) { char buffer[128]; /* * XXX Need to keep the input on a single line since the display screws * up if it wraps around. */ snprintf(buffer, sizeof(buffer), "set completion-ignore-case %s", this->rc_case_sensitive ? "off" : "on"); rl_parse_and_bind(buffer); /* NOTE: buffer is modified */ loaded_context = this; rl_attempted_completion_function = attempted_completion; history_set_history_state(&this->rc_history); }; void save(void) { HISTORY_STATE *hs = history_get_history_state(); this->rc_history = *hs; free(hs); hs = NULL; }; void add_possibility(std::string type, std::string value) { this->rc_possibilities[type].insert(value); }; void rem_possibility(std::string type, std::string value) { this->rc_possibilities[type].erase(value); }; void clear_possibilities(std::string type) { this->rc_possibilities[type].clear(); }; bool is_case_sensitive(void) const { return this->rc_case_sensitive; }; readline_context &set_append_character(int ch) { this->rc_append_character = ch; return *this; }; readline_context &set_highlighter(readline_highlighter_t hl) { this->rc_highlighter = hl; return *this; }; readline_highlighter_t get_highlighter() const { return this->rc_highlighter; }; private: static char **attempted_completion(const char *text, int start, int end); static char *completion_generator(const char *text, int state); static readline_context * loaded_context; static std::set *arg_possibilities; std::string rc_name; HISTORY_STATE rc_history; std::map > rc_possibilities; std::map > rc_prototypes; bool rc_case_sensitive; int rc_append_character; readline_highlighter_t rc_highlighter; }; /** * Adapter between readline and curses. The curses and readline libraries * normally do not get along. So, we need to put readline in another process * and present it with a vt52 interface that we then translate to curses. The * vt52 translation is done by the parent class, vt52_curses, while this class * takes care of the communication between the two processes. */ class readline_curses : public vt52_curses { public: typedef view_action action; class error : public std::exception { public: error(int err) : e_err(err) { }; int e_err; }; static const int KEY_TIMEOUT = 750 * 1000; static const int VALUE_EXPIRATION = 20; readline_curses(); virtual ~readline_curses(); void add_context(int id, readline_context &rc) { this->rc_contexts[id] = &rc; }; void set_perform_action(action va) { this->rc_perform = va; }; void set_timeout_action(action va) { this->rc_timeout = va; }; void set_abort_action(action va) { this->rc_abort = va; }; void set_display_match_action(action va) { this->rc_display_match = va; }; void set_display_next_action(action va) { this->rc_display_next = va; }; void set_value(const std::string &value) { this->rc_value = value; this->rc_value_expiration = time(NULL) + VALUE_EXPIRATION; }; std::string get_value() const { return this->rc_value; }; void set_alt_value(const std::string &value) { this->rc_alt_value = value; }; std::string get_alt_value() const { return this->rc_alt_value; }; int update_fd_set(fd_set &readfds) { FD_SET(this->rc_pty[RCF_MASTER], &readfds); FD_SET(this->rc_command_pipe[RCF_MASTER], &readfds); return std::max(this->rc_pty[RCF_MASTER].get(), this->rc_command_pipe[RCF_MASTER].get()); }; void handle_key(int ch); void check_fd_set(fd_set &ready_rfds); void focus(int context, const char *prompt); void abort(); void start(void); void do_update(void); void window_change(void) { struct winsize ws; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1) { throw error(errno); } if (ioctl(this->rc_pty[RCF_MASTER], TIOCSWINSZ, &ws) == -1) { throw error(errno); } }; void line_ready(const char *line); void add_possibility(int context, const std::string &type, const std::string &value); void add_possibility(int context, const std::string &type, const char *values[]) { for (int lpc = 0; values[lpc]; lpc++) { this->add_possibility(context, type, values[lpc]); } }; void rem_possibility(int context, const std::string &type, const std::string &value); void clear_possibilities(int context, std::string type); const std::vector &get_matches() const { return this->rc_matches; }; int get_max_match_length() const { return this->rc_max_match_length; }; private: enum { RCF_MASTER, RCF_SLAVE, RCF_MAX_VALUE, }; static void store_matches(char **matches, int num_matches, int max_len); friend class readline_context; int rc_active_context; pid_t rc_child; auto_fd rc_pty[2]; auto_fd rc_command_pipe[2]; std::map rc_contexts; std::string rc_value; time_t rc_value_expiration; std::string rc_alt_value; int rc_matches_remaining; int rc_max_match_length; std::vector rc_matches; action rc_perform; action rc_timeout; action rc_abort; action rc_display_match; action rc_display_next; }; #endif lnav-0.7.0/src/readline_highlighters.cc000664 000765 000024 00000032662 12307160745 020370 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file readline_highlighters.cc */ #include "config.h" #include "pcrepp.hh" #include "sql_util.hh" #include "readline_highlighters.hh" using namespace std; static bool check_re_prev(const string &line, int x) { bool retval = false; if ((x > 0 && line[x - 1] != ')' && line[x - 1] != ']' && line[x - 1] != '*' && line[x - 1] != '?' && line[x - 1] != '+') && (x < 2 || line[x - 2] != '\\')) { retval = true; } return retval; } static bool is_bracket(const string &str, int index, bool is_lit) { if (is_lit && str[index - 1] == '\\') { return true; } if (!is_lit && str[index - 1] != '\\') { return true; } return false; } static void find_matching_bracket(attr_line_t &al, int x, char left, char right) { static int matching_bracket_attrs = ( A_BOLD|A_REVERSE|view_colors::ansi_color_pair(COLOR_GREEN, COLOR_BLACK)); static int missing_bracket_attrs = ( A_BOLD|A_REVERSE|view_colors::ansi_color_pair(COLOR_RED, COLOR_BLACK)); bool is_lit = (left == 'Q'); const string &line = al.get_string(); if (line[x] == right && is_bracket(line, x, is_lit)) { for (int lpc = x; lpc > 0; lpc--) { if (line[lpc] == left && is_bracket(line, lpc, is_lit)) { al.get_attrs().push_back(string_attr( line_range(lpc, lpc + 1), &view_curses::VC_STYLE, matching_bracket_attrs)); break; } } } if (line[x] == left && is_bracket(line, x, is_lit)) { for (int lpc = x; lpc < line.length(); lpc++) { if (line[lpc] == right && is_bracket(line, lpc, is_lit)) { al.get_attrs().push_back(string_attr( line_range(lpc, lpc + 1), &view_curses::VC_STYLE, matching_bracket_attrs)); break; } } } int depth = 0, last_left = -1; for (int lpc = 1; lpc < line.length(); lpc++) { if (line[lpc] == left && is_bracket(line, lpc, is_lit)) { depth += 1; last_left = lpc; } else if (line[lpc] == right && is_bracket(line, lpc, is_lit)) { if (depth > 0) { depth -= 1; } else { al.get_attrs().push_back(string_attr( line_range(is_lit ? lpc - 1 : lpc, lpc + 1), &view_curses::VC_STYLE, missing_bracket_attrs)); } } } if (depth > 0) { al.get_attrs().push_back(string_attr( line_range(is_lit ? last_left - 1 : last_left, last_left + 1), &view_curses::VC_STYLE, missing_bracket_attrs)); } } static char safe_read(const string &str, string::size_type index) { if (index < str.length()) { return str.at(index); } return 0; } void readline_regex_highlighter(attr_line_t &al, int x) { static int special_char = ( A_BOLD|view_colors::ansi_color_pair(COLOR_CYAN, COLOR_BLACK)); static int class_attrs = ( A_BOLD|view_colors::ansi_color_pair(COLOR_MAGENTA, COLOR_BLACK)); static int repeated_char_attrs = ( view_colors::ansi_color_pair(COLOR_YELLOW, COLOR_BLACK)); static int bracket_attrs = ( view_colors::ansi_color_pair(COLOR_GREEN, COLOR_BLACK)); static int error_attrs = ( A_BOLD|A_REVERSE|view_colors::ansi_color_pair(COLOR_RED, COLOR_BLACK)); static const char *brackets[] = { "[]", "{}", "()", "QE", NULL }; string &line = al.get_string(); bool backslash_is_quoted = false; for (int lpc = 1; lpc < line.length(); lpc++) { if (line[lpc - 1] != '\\') { switch (line[lpc]) { case '^': case '$': case '*': case '+': case '|': case '.': al.get_attrs().push_back(string_attr( line_range(lpc, lpc + 1), &view_curses::VC_STYLE, special_char)); if ((line[lpc] == '*' || line[lpc] == '+') && check_re_prev(line, lpc)) { al.get_attrs().push_back(string_attr( line_range(lpc - 1, lpc), &view_curses::VC_STYLE, repeated_char_attrs)); } break; case '?': { struct line_range lr(lpc, lpc + 1); if (line[lpc - 1] == '(') { switch (line[lpc + 1]) { case ':': case '!': case '>': case '<': case '#': lr.lr_end += 1; break; } al.get_attrs().push_back(string_attr( lr, &view_curses::VC_STYLE, bracket_attrs)); } else { al.get_attrs().push_back(string_attr( lr, &view_curses::VC_STYLE, special_char)); if (check_re_prev(line, lpc)) { al.get_attrs().push_back(string_attr( line_range(lpc - 1, lpc), &view_curses::VC_STYLE, repeated_char_attrs)); } } break; } case '(': case ')': case '{': case '}': case '[': case ']': al.get_attrs().push_back(string_attr( line_range(lpc, lpc + 1), &view_curses::VC_STYLE, bracket_attrs)); break; } } if (line[lpc - 1] == '\\') { if (backslash_is_quoted) { backslash_is_quoted = false; continue; } switch (line[lpc]) { case '\\': backslash_is_quoted = true; al.with_attr(string_attr( line_range(lpc - 1, lpc + 1), &view_curses::VC_STYLE, special_char)); break; case 'd': case 'D': case 'h': case 'H': case 'N': case 'R': case 's': case 'S': case 'v': case 'V': case 'w': case 'W': case 'X': case 'A': case 'b': case 'B': case 'G': case 'Z': case 'z': al.get_attrs().push_back(string_attr( line_range(lpc - 1, lpc + 1), &view_curses::VC_STYLE, class_attrs)); break; case ' ': al.get_attrs().push_back(string_attr( line_range(lpc - 1, lpc + 1), &view_curses::VC_STYLE, error_attrs)); break; case '0': case 'x': if (safe_read(line, lpc + 1) == '{') { al.with_attr(string_attr( line_range(lpc - 1, lpc + 1), &view_curses::VC_STYLE, special_char)); } else if (isdigit(safe_read(line, lpc + 1)) && isdigit(safe_read(line, lpc + 2))) { al.with_attr(string_attr( line_range(lpc - 1, lpc + 3), &view_curses::VC_STYLE, special_char)); } else { al.with_attr(string_attr( line_range(lpc - 1, lpc + 1), &view_curses::VC_STYLE, error_attrs)); } break; case 'Q': case 'E': al.with_attr(string_attr( line_range(lpc - 1, lpc + 1), &view_curses::VC_STYLE, bracket_attrs)); break; default: if (isdigit(line[lpc])) { al.get_attrs().push_back(string_attr( line_range(lpc - 1, lpc + 1), &view_curses::VC_STYLE, special_char)); } break; } } } for (int lpc = 0; brackets[lpc]; lpc++) { find_matching_bracket(al, x, brackets[lpc][0], brackets[lpc][1]); } } static string sql_keyword_re(void) { string retval = "(?:"; for (int lpc = 0; sql_keywords[lpc]; lpc++) { if (lpc > 0) { retval.append("|"); } retval.append("\\b"); retval.append(sql_keywords[lpc]); retval.append("\\b"); } retval += ")"; return retval; } void readline_sqlite_highlighter(attr_line_t &al, int x) { static int keyword_attrs = ( A_BOLD|view_colors::ansi_color_pair(COLOR_CYAN, COLOR_BLACK)); static int symbol_attrs = ( view_colors::ansi_color_pair(COLOR_MAGENTA, COLOR_BLACK)); static int string_attrs = ( view_colors::ansi_color_pair(COLOR_GREEN, COLOR_BLACK)); static int error_attrs = ( A_BOLD|A_REVERSE|view_colors::ansi_color_pair(COLOR_RED, COLOR_BLACK)); static string keyword_re_str = sql_keyword_re() + "|\\.schema"; static pcrepp keyword_pcre(keyword_re_str.c_str(), PCRE_CASELESS); static pcrepp string_literal_pcre("'[^']*('(?:'[^']*')*|$)"); static pcrepp ident_pcre("(\\b[a-z_]\\w*)|\"([^\"]+)\"|\\[([^\\]]+)]", PCRE_CASELESS); static const char *brackets[] = { "[]", "()", NULL }; view_colors &vc = view_colors::singleton(); pcre_context_static<30> pc; pcre_input pi(al.get_string()); string &line = al.get_string(); while (ident_pcre.match(pc, pi)) { pcre_context::capture_t *cap = pc.first_valid(); int attrs = vc.attrs_for_ident(pi.get_substr_start(cap), cap->length()); struct line_range lr(cap->c_begin, cap->c_end); if (line[cap->c_end] == '(') { } else if (!lr.contains(x) && !lr.contains(x - 1)) { al.get_attrs().push_back(string_attr( lr, &view_curses::VC_STYLE, attrs)); } } pi.reset(line); while (keyword_pcre.match(pc, pi)) { pcre_context::capture_t *cap = pc.all(); al.get_attrs().push_back(string_attr( line_range(cap->c_begin, cap->c_end), &view_curses::VC_STYLE, keyword_attrs)); } for (int lpc = 0; lpc < line.length(); lpc++) { switch (line[lpc]) { case '*': case '<': case '>': case '=': case '!': case '-': case '+': al.get_attrs().push_back(string_attr( line_range(lpc, lpc + 1), &view_curses::VC_STYLE, symbol_attrs)); break; } } pi.reset(line); while (string_literal_pcre.match(pc, pi)) { pcre_context::capture_t *cap = pc.all(); struct line_range lr(cap->c_begin, cap->c_end); string_attrs_t &sa = al.get_attrs(); remove_string_attr(sa, lr); if (line[cap->c_end - 1] != '\'') { sa.push_back(string_attr( line_range(cap->c_begin, cap->c_begin + 1), &view_curses::VC_STYLE, error_attrs)); lr.lr_start += 1; } sa.push_back(string_attr( lr, &view_curses::VC_STYLE, string_attrs)); } for (int lpc = 0; brackets[lpc]; lpc++) { find_matching_bracket(al, x, brackets[lpc][0], brackets[lpc][1]); } } lnav-0.7.0/src/readline_highlighters.hh000644 000765 000024 00000003412 12305355011 020355 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file readline_highlighters.hh */ #ifndef __readline_highlighters_hh #define __readline_highlighters_hh #include "view_curses.hh" void readline_regex_highlighter(attr_line_t &line, int x); void readline_sqlite_highlighter(attr_line_t &line, int x); #endif lnav-0.7.0/src/sequence_matcher.cc000664 000765 000024 00000005643 12274220650 017351 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "spookyhash/SpookyV2.h" #include "sequence_matcher.hh" using namespace std; sequence_matcher::sequence_matcher(field_col_t &example) { for (field_col_t::iterator col_iter = example.begin(); col_iter != example.end(); ++col_iter) { std::string first_value; field sf; sf.sf_value = *col_iter; for (field_row_t::iterator row_iter = (*col_iter).begin(); row_iter != (*col_iter).end(); ++row_iter) { if (row_iter == (*col_iter).begin()) { first_value = *row_iter; } else if (first_value != *row_iter) { sf.sf_type = FT_CONSTANT; } } if (sf.sf_type == FT_VARIABLE) { sf.sf_value.clear(); } this->sm_fields.push_back(sf); } this->sm_count = example.front().size(); } void sequence_matcher::identity(const std::vector &values, id_t &id_out) { SpookyHash context; int lpc = 0; context.Init(0, 0); for (std::list::iterator iter = sm_fields.begin(); iter != sm_fields.end(); ++iter, lpc++) { if (iter->sf_type == FT_VARIABLE) { context.Update( values[lpc].c_str(), values[lpc].length() + 1); } } context.Final(id_out.out(0), id_out.out(1)); } lnav-0.7.0/src/sequence_matcher.hh000664 000765 000024 00000006211 12274220615 017354 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __sequence_matcher_hh #define __sequence_matcher_hh #include #include #include #include "byte_array.hh" class sequence_matcher { public: typedef std::vector field_row_t; typedef std::list field_col_t; typedef byte_array<2, uint64_t> id_t; enum field_type_t { FT_VARIABLE, FT_CONSTANT, }; struct field { field() : sf_type(FT_VARIABLE) { }; field_type_t sf_type; field_row_t sf_value; }; sequence_matcher(field_col_t &example); void identity(const std::vector &values, id_t &id_out); template bool match(const std::vector &values, std::vector &state, T index) { bool index_match = true; int lpc = 0; retry: for (std::list::iterator iter = this->sm_fields.begin(); iter != this->sm_fields.end(); ++iter, lpc++) { if (iter->sf_type != sequence_matcher::FT_CONSTANT) { continue; } if (iter->sf_value[state.size()] != values[lpc]) { if (!state.empty()) { state.clear(); lpc = 0; goto retry; } else { index_match = false; break; } } } if (index_match) { state.push_back(index); } return this->sm_count == state.size(); }; private: int sm_count; std::list sm_fields; }; #endif lnav-0.7.0/src/sequence_sink.hh000664 000765 000024 00000006434 12211635054 016702 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __sequence_sink_hh #define __sequence_sink_hh #include #include "bookmarks.hh" #include "grep_proc.hh" #include "sequence_matcher.hh" class sequence_sink : public grep_proc_sink { public: sequence_sink(sequence_matcher &sm, bookmark_vector &bv) : ss_matcher(sm), ss_bookmarks(bv) {}; void grep_match(grep_proc &gp, grep_line_t line, int start, int end) { this->ss_line_values.clear(); }; void grep_capture(grep_proc &gp, grep_line_t line, int start, int end, char *capture) { if (start == -1) { this->ss_line_values.push_back(""); } else{ this->ss_line_values.push_back(std::string(capture)); } }; void grep_match_end(grep_proc &gp, grep_line_t line) { sequence_matcher::id_t line_id; this->ss_matcher.identity(this->ss_line_values, line_id); std::vector &line_state = this->ss_state[line_id]; if (this->ss_matcher.match(this->ss_line_values, line_state, line)) { std::vector::iterator iter; for (iter = line_state.begin(); iter != line_state.end(); ++iter) { this->ss_bookmarks.insert_once(vis_line_t(*iter)); } line_state.clear(); } }; private: sequence_matcher & ss_matcher; bookmark_vector &ss_bookmarks; std::vector ss_line_values; std::map > ss_state; }; #endif lnav-0.7.0/src/session_data.cc000664 000765 000024 00000125326 12312224211 016501 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file session_data.cc */ #include "config.h" #include #include #include #include #include #include "spookyhash/SpookyV2.h" #include #include "yajlpp.hh" #include "lnav.hh" #include "logfile.hh" #include "sql_util.hh" #include "lnav_util.hh" #include "lnav_config.hh" #include "session_data.hh" using namespace std; static const char *LOG_METADATA_NAME = "log_metadata.db"; static const char *BOOKMARK_TABLE_DEF = "CREATE TABLE IF NOT EXISTS bookmarks (\n" " log_time datetime,\n" " log_format varchar(64),\n" " log_hash varchar(128),\n" " session_time integer,\n" " part_name text,\n" " access_time datetime DEFAULT CURRENT_TIMESTAMP,\n" "\n" " PRIMARY KEY (log_time, log_format, log_hash, session_time)\n" ");\n" "CREATE TABLE IF NOT EXISTS time_offset (\n" " log_time datetime,\n" " log_format varchar(64),\n" " log_hash varchar(128),\n" " session_time integer,\n" " offset_sec integer,\n" " offset_usec integer,\n" " access_time datetime DEFAULT CURRENT_TIMESTAMP,\n" "\n" " PRIMARY KEY (log_time, log_format, log_hash, session_time)\n" ");\n"; static const char *BOOKMARK_LRU_STMT = "DELETE FROM bookmarks WHERE access_time <= " " (SELECT access_time FROM bookmarks " " ORDER BY access_time DESC LIMIT 1 OFFSET 50000)"; static const size_t MAX_SESSIONS = 8; static const size_t MAX_SESSION_FILE_COUNT = 256; typedef std::vector > timestamped_list_t; static std::vector marked_session_lines; static std::vector offset_session_lines; static bool bind_line(sqlite3 *db, sqlite3_stmt *stmt, content_line_t cl, time_t session_time) { logfile_sub_source &lss = lnav_data.ld_log_source; logfile::iterator line_iter; logfile *lf; lf = lss.find(cl); if (lf == NULL) { return false; } line_iter = lf->begin() + cl; char timestamp[64]; sql_strftime(timestamp, sizeof(timestamp), lf->original_line_time(line_iter), 'T'); if (sqlite3_bind_text(stmt, 1, timestamp, strlen(timestamp), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind log time -- %s\n", sqlite3_errmsg(db)); return false; } const std::string &format_name = lf->get_format()->get_name(); if (sqlite3_bind_text(stmt, 2, format_name.c_str(), format_name.length(), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind log format -- %s\n", sqlite3_errmsg(db)); return false; } std::string line_hash = hash_string(lf->read_line(line_iter)); if (sqlite3_bind_text(stmt, 3, line_hash.c_str(), line_hash.length(), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind log hash -- %s\n", sqlite3_errmsg(db)); return false; } if (sqlite3_bind_int64(stmt, 4, session_time) != SQLITE_OK) { fprintf(stderr, "error: could not bind session time -- %s\n", sqlite3_errmsg(db)); return false; } return true; } struct session_file_info { session_file_info(int timestamp, const string &id, const string &path) : sfi_timestamp(timestamp), sfi_id(id), sfi_path(path) {}; bool operator<(const session_file_info &other) const { if (this->sfi_timestamp < other.sfi_timestamp) { return true; } if (this->sfi_path < other.sfi_path) { return true; } return false; }; int sfi_timestamp; string sfi_id; string sfi_path; }; static void cleanup_session_data(void) { static_root_mem session_file_list; std::list session_info_list; map session_count; string session_file_pattern; session_file_pattern = dotlnav_path("*-*.ts*.json"); if (glob(session_file_pattern.c_str(), 0, NULL, session_file_list.inout()) == 0) { for (size_t lpc = 0; lpc < session_file_list->gl_pathc; lpc++) { const char *path = session_file_list->gl_pathv[lpc]; char hash_id[64]; int timestamp; const char *base; base = strrchr(path, '/') + 1; if (sscanf(base, "file-%63[^.].ts%d.json", hash_id, ×tamp) == 2) { session_count[hash_id] += 1; session_info_list.push_back(session_file_info( timestamp, hash_id, path)); } if (sscanf(base, "view-info-%63[^.].ts%d.ppid%*d.json", hash_id, ×tamp) == 2) { session_count[hash_id] += 1; session_info_list.push_back(session_file_info( timestamp, hash_id, path)); } } } session_info_list.sort(); size_t session_loops = 0; while (session_info_list.size() > MAX_SESSION_FILE_COUNT) { const session_file_info &front = session_info_list.front(); session_loops += 1; if (session_loops < MAX_SESSION_FILE_COUNT && session_count[front.sfi_id] == 1) { session_info_list.splice(session_info_list.end(), session_info_list, session_info_list.begin()); } else { if (remove(front.sfi_path.c_str()) != 0) { fprintf(stderr, "error: Unable to remove session file: %s -- %s\n", front.sfi_path.c_str(), strerror(errno)); } session_count[front.sfi_id] -= 1; session_info_list.pop_front(); } } session_info_list.sort(); while (session_info_list.size() > MAX_SESSION_FILE_COUNT) { const session_file_info &front = session_info_list.front(); if (remove(front.sfi_path.c_str()) != 0) { fprintf(stderr, "error: Unable to remove session file: %s -- %s\n", front.sfi_path.c_str(), strerror(errno)); } session_count[front.sfi_id] -= 1; session_info_list.pop_front(); } } void init_session(void) { byte_array<2, uint64> hash; SpookyHash context; lnav_data.ld_session_time = time(NULL); context.Init(0, 0); hash_updater updater(&context); for_each(lnav_data.ld_file_names.begin(), lnav_data.ld_file_names.end(), object_field(updater, &pair::first)); context.Final(hash.out(0), hash.out(1)); lnav_data.ld_session_id = hash.to_string(); log_info("init_session: time=%d; id=%s", lnav_data.ld_session_time, lnav_data.ld_session_id.c_str()); } void scan_sessions(void) { std::list &session_file_names = lnav_data.ld_session_file_names; static_root_mem view_info_list; std::list::iterator iter; char view_info_pattern_base[128]; string view_info_pattern; string old_session_name; int index; cleanup_session_data(); if (lnav_data.ld_session_file_index >= 0 && lnav_data.ld_session_file_index < (int)session_file_names.size()) { iter = session_file_names.begin(); advance(iter, lnav_data.ld_session_file_index); old_session_name = iter->second; } session_file_names.clear(); snprintf(view_info_pattern_base, sizeof(view_info_pattern_base), "view-info-%s.*.json", lnav_data.ld_session_id.c_str()); view_info_pattern = dotlnav_path(view_info_pattern_base); if (glob(view_info_pattern.c_str(), 0, NULL, view_info_list.inout()) == 0) { for (size_t lpc = 0; lpc < view_info_list->gl_pathc; lpc++) { const char *path = view_info_list->gl_pathv[lpc]; int timestamp, ppid; const char *base; base = strrchr(path, '/') + 1; if (sscanf(base, "view-info-%*[^.].ts%d.ppid%d.json", ×tamp, &ppid) == 2) { ppid_time_pair_t ptp; ptp.first = (ppid == getppid()) ? 1 : 0; ptp.second = timestamp; session_file_names.push_back(make_pair(ptp, path)); } } } session_file_names.sort(); while (session_file_names.size() > MAX_SESSIONS) { const std::string &name = session_file_names.front().second; if (remove(name.c_str()) != 0) { fprintf(stderr, "error: Unable to remove session: %s -- %s\n", name.c_str(), strerror(errno)); } session_file_names.pop_front(); } lnav_data.ld_session_file_index = ((int)session_file_names.size()) - 1; for (index = 0, iter = session_file_names.begin(); iter != session_file_names.end(); index++, ++iter) { if (iter->second == old_session_name) { lnav_data.ld_session_file_index = index; break; } } } static void load_time_bookmarks(void) { logfile_sub_source &lss = lnav_data.ld_log_source; std::map &bm_meta = lss.get_user_bookmark_metadata(); auto_mem db; string db_path = dotlnav_path(LOG_METADATA_NAME); auto_mem stmt(sqlite3_finalize); logfile_sub_source::iterator file_iter; log_info("loading bookmark db: %s", db_path.c_str()); if (sqlite3_open(db_path.c_str(), db.out()) != SQLITE_OK) { return; } if (sqlite3_prepare_v2(db.in(), "SELECT *,session_time=? as same_session FROM bookmarks WHERE " " log_time between ? and ? and log_format = ? " " ORDER BY same_session DESC, session_time DESC", -1, stmt.out(), NULL) != SQLITE_OK) { fprintf(stderr, "error: could not prepare bookmark select statemnt -- %s\n", sqlite3_errmsg(db)); return; } for (file_iter = lnav_data.ld_log_source.begin(); file_iter != lnav_data.ld_log_source.end(); ++file_iter) { char low_timestamp[64], high_timestamp[64]; logfile *lf = file_iter->ld_file; content_line_t base_content_line; if (lf == NULL) continue; base_content_line = lss.get_file_base_content_line(file_iter); logfile::iterator line_iter = lf->begin(); sql_strftime(low_timestamp, sizeof(low_timestamp), lf->original_line_time(line_iter), 'T'); if (sqlite3_bind_int64(stmt.in(), 1, lnav_data.ld_session_load_time) != SQLITE_OK) { fprintf(stderr, "error: could not bind session time -- %s\n", sqlite3_errmsg(db.in())); return; } if (sqlite3_bind_text(stmt.in(), 2, low_timestamp, strlen(low_timestamp), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind low log time -- %s\n", sqlite3_errmsg(db.in())); return; } line_iter = lf->end(); --line_iter; sql_strftime(high_timestamp, sizeof(high_timestamp), lf->original_line_time(line_iter), 'T'); if (sqlite3_bind_text(stmt.in(), 3, high_timestamp, strlen(high_timestamp), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind high log time -- %s\n", sqlite3_errmsg(db.in())); return; } const std::string &format_name = lf->get_format()->get_name(); if (sqlite3_bind_text(stmt.in(), 4, format_name.c_str(), format_name.length(), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind log format -- %s\n", sqlite3_errmsg(db.in())); return; } date_time_scanner dts; bool done = false; string line; int64_t last_mark_time = -1; while (!done) { int rc = sqlite3_step(stmt.in()); switch (rc) { case SQLITE_OK: case SQLITE_DONE: done = true; break; case SQLITE_ROW: { const char *log_time = (const char *)sqlite3_column_text(stmt.in(), 0); const char *log_hash = (const char *)sqlite3_column_text(stmt.in(), 2); const char *part_name = (const char *)sqlite3_column_text(stmt.in(), 4); int64_t mark_time = sqlite3_column_int64(stmt.in(), 3); struct timeval log_tv; struct tm log_tm; if (last_mark_time == -1) { last_mark_time = mark_time; } else if (last_mark_time != mark_time) { done = true; continue; } if (part_name == NULL) { continue; } if (!dts.scan(log_time, NULL, &log_tm, log_tv)) { continue; } line_iter = lower_bound(lf->begin(), lf->end(), log_tv); while (line_iter != lf->end()) { struct timeval line_tv = line_iter->get_timeval(); if ((line_tv.tv_sec != log_tv.tv_sec) || (line_tv.tv_usec != log_tv.tv_usec)) { break; } lf->read_line(line_iter, line); string line_hash = hash_string(line); if (line_hash == log_hash) { content_line_t line_cl = content_line_t( base_content_line + std::distance(lf->begin(), line_iter)); if (part_name != NULL && part_name[0] != '\0') { lss.set_user_mark(&textview_curses::BM_PARTITION, line_cl); bm_meta[line_cl].bm_name = part_name; } else { marked_session_lines.push_back(line_cl); lss.set_user_mark(&textview_curses::BM_USER, line_cl); } } ++line_iter; } break; } default: { const char *errmsg; errmsg = sqlite3_errmsg(lnav_data.ld_db); fprintf(stderr, "error: bookmark select error: code %d -- %s\n", rc, errmsg); done = true; } break; } } sqlite3_reset(stmt.in()); } if (sqlite3_prepare_v2(db.in(), "SELECT *,session_time=? as same_session FROM time_offset WHERE " " log_time between ? and ? and log_format = ? " " ORDER BY same_session DESC, session_time DESC", -1, stmt.out(), NULL) != SQLITE_OK) { fprintf(stderr, "error: could not prepare time_offset select statemnt -- %s\n", sqlite3_errmsg(db)); return; } for (file_iter = lnav_data.ld_log_source.begin(); file_iter != lnav_data.ld_log_source.end(); ++file_iter) { char low_timestamp[64], high_timestamp[64]; logfile *lf = file_iter->ld_file; content_line_t base_content_line; if (lf == NULL) continue; lss.find(lf->get_filename().c_str(), base_content_line); logfile::iterator line_iter = lf->begin(); sql_strftime(low_timestamp, sizeof(low_timestamp), lf->original_line_time(line_iter), 'T'); if (sqlite3_bind_int64(stmt.in(), 1, lnav_data.ld_session_load_time) != SQLITE_OK) { fprintf(stderr, "error: could not bind session time -- %s\n", sqlite3_errmsg(db.in())); return; } if (sqlite3_bind_text(stmt.in(), 2, low_timestamp, strlen(low_timestamp), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind low log time -- %s\n", sqlite3_errmsg(db.in())); return; } line_iter = lf->end(); --line_iter; sql_strftime(high_timestamp, sizeof(high_timestamp), lf->original_line_time(line_iter), 'T'); if (sqlite3_bind_text(stmt.in(), 3, high_timestamp, strlen(high_timestamp), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind high log time -- %s\n", sqlite3_errmsg(db.in())); return; } const std::string &format_name = lf->get_format()->get_name(); if (sqlite3_bind_text(stmt.in(), 4, format_name.c_str(), format_name.length(), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind log format -- %s\n", sqlite3_errmsg(db.in())); return; } date_time_scanner dts; bool done = false; string line; int64_t last_mark_time = -1; while (!done) { int rc = sqlite3_step(stmt.in()); switch (rc) { case SQLITE_OK: case SQLITE_DONE: done = true; break; case SQLITE_ROW: { const char *log_time = (const char *)sqlite3_column_text(stmt.in(), 0); const char *log_hash = (const char *)sqlite3_column_text(stmt.in(), 2); int64_t mark_time = sqlite3_column_int64(stmt.in(), 3); struct timeval log_tv; struct tm log_tm; if (last_mark_time == -1) { last_mark_time = mark_time; } else if (last_mark_time != mark_time) { done = true; continue; } if (sqlite3_column_type(stmt.in(), 4) == SQLITE_NULL) { continue; } if (!dts.scan(log_time, NULL, &log_tm, log_tv)) { continue; } line_iter = lower_bound(lf->begin(), lf->end(), log_tv); while (line_iter != lf->end()) { struct timeval line_tv = line_iter->get_timeval(); if ((line_tv.tv_sec != log_tv.tv_sec) || (line_tv.tv_usec != log_tv.tv_usec)) { break; } lf->read_line(line_iter, line); string line_hash = hash_string(line); if (line_hash == log_hash) { int file_line = std::distance(lf->begin(), line_iter); content_line_t line_cl = content_line_t( base_content_line + file_line); struct timeval offset; offset_session_lines.push_back(line_cl); offset.tv_sec = sqlite3_column_int64(stmt.in(), 4); offset.tv_usec = sqlite3_column_int64(stmt.in(), 5); lf->adjust_content_time(file_line, offset); } ++line_iter; } break; } default: { const char *errmsg; errmsg = sqlite3_errmsg(lnav_data.ld_db); fprintf(stderr, "error: bookmark select error: code %d -- %s\n", rc, errmsg); done = true; } break; } } sqlite3_reset(stmt.in()); } } static int read_save_time(yajlpp_parse_context *ypc, long long value) { lnav_data.ld_session_save_time = value; return 1; } static int read_time_offset(yajlpp_parse_context *ypc, int value) { lnav_data.ld_log_source.set_time_offset(value); return 1; } static int read_files(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { return 1; } static int read_last_search(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { string regex = std::string((const char *)str, len); const char **view_name; int view_index; view_name = find(lnav_view_strings, lnav_view_strings + LNV__MAX, ypc->get_path_fragment(-2)); view_index = view_name - lnav_view_strings; if (view_index < LNV__MAX && !regex.empty()) { execute_search((lnav_view_t)view_index, regex); lnav_data.ld_views[view_index].set_follow_search(false); } return 1; } static int read_top_line(yajlpp_parse_context *ypc, long long value) { const char ** view_name; int view_index; view_name = find(lnav_view_strings, lnav_view_strings + LNV__MAX, ypc->get_path_fragment(-2)); view_index = view_name - lnav_view_strings; if (view_index < LNV__MAX) { textview_curses &tc = lnav_data.ld_views[view_index]; if (value != -1 && value < tc.get_inner_height()) { tc.set_top(vis_line_t(value)); } } return 1; } static int read_word_wrap(yajlpp_parse_context *ypc, int value) { const char ** view_name; int view_index; view_name = find(lnav_view_strings, lnav_view_strings + LNV__MAX, ypc->get_path_fragment(-2)); view_index = view_name - lnav_view_strings; if (view_index == LNV_HELP) { } else if (view_index < LNV__MAX) { textview_curses &tc = lnav_data.ld_views[view_index]; tc.set_word_wrap(value); } return 1; } static int read_commands(yajlpp_parse_context *ypc, const unsigned char *str, size_t len) { std::string cmdline = std::string((const char *)str, len); execute_command(cmdline); return 1; } static struct json_path_handler view_info_handlers[] = { json_path_handler("/save-time", read_save_time), json_path_handler("/time-offset", read_time_offset), json_path_handler("/files#", read_files), json_path_handler("/views/([^/]+)/top_line", read_top_line), json_path_handler("/views/([^/]+)/search", read_last_search), json_path_handler("/views/([^/]+)/word_wrap", read_word_wrap), json_path_handler("/commands#", read_commands), json_path_handler() }; void load_session(void) { std::list::iterator sess_iter; yajl_handle handle; auto_fd fd; if (lnav_data.ld_session_file_names.empty()) { load_time_bookmarks(); return; } sess_iter = lnav_data.ld_session_file_names.begin(); advance(sess_iter, lnav_data.ld_session_file_index); lnav_data.ld_session_load_time = sess_iter->first.second; lnav_data.ld_session_save_time = sess_iter->first.second; string &view_info_name = sess_iter->second; yajlpp_parse_context ypc(view_info_name, view_info_handlers); handle = yajl_alloc(&ypc.ypc_callbacks, NULL, &ypc); load_time_bookmarks(); if ((fd = open(view_info_name.c_str(), O_RDONLY)) < 0) { perror("cannot open session file"); } else { unsigned char buffer[1024]; size_t rc; log_info("loading session file: %s", view_info_name.c_str()); while ((rc = read(fd, buffer, sizeof(buffer))) > 0) { yajl_parse(handle, buffer, rc); } yajl_complete_parse(handle); } yajl_free(handle); } static void yajl_writer(void *context, const char *str, size_t len) { FILE *file = (FILE *)context; fwrite(str, len, 1, file); } static void save_user_bookmarks( sqlite3 *db, sqlite3_stmt *stmt, bookmark_vector &user_marks) { logfile_sub_source &lss = lnav_data.ld_log_source; std::map &bm_meta = lss.get_user_bookmark_metadata(); bookmark_vector::iterator iter; for (iter = user_marks.begin(); iter != user_marks.end(); ++iter) { std::map::iterator meta_iter; logfile::iterator line_iter; content_line_t cl = *iter; meta_iter = bm_meta.find(cl); marked_session_lines.push_back(cl); if (!bind_line(db, stmt, cl, lnav_data.ld_session_time)) { continue; } if (meta_iter == bm_meta.end()) { if (sqlite3_bind_text(stmt, 5, "", 0, SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind log hash -- %s\n", sqlite3_errmsg(db)); return; } } else { if (sqlite3_bind_text(stmt, 5, meta_iter->second.bm_name.c_str(), meta_iter->second.bm_name.length(), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind log hash -- %s\n", sqlite3_errmsg(db)); return; } } if (sqlite3_step(stmt) != SQLITE_DONE) { fprintf(stderr, "error: could not execute bookmark insert statement -- %s\n", sqlite3_errmsg(db)); return; } sqlite3_reset(stmt); } } static void save_time_bookmarks(void) { auto_mem db; string db_path = dotlnav_path(LOG_METADATA_NAME); auto_mem errmsg; auto_mem stmt(sqlite3_finalize); if (sqlite3_open(db_path.c_str(), db.out()) != SQLITE_OK) { fprintf(stderr, "error: unable to open bookmark DB -- %s\n", db_path.c_str()); return; } if (sqlite3_exec(db.in(), BOOKMARK_TABLE_DEF, NULL, NULL, errmsg.out()) != SQLITE_OK) { fprintf(stderr, "error: unable to make bookmark table -- %s\n", errmsg.in()); return; } if (sqlite3_exec(db.in(), "BEGIN TRANSACTION", NULL, NULL, errmsg.out()) != SQLITE_OK) { fprintf(stderr, "error: unable to begin transaction -- %s\n", errmsg.in()); return; } logfile_sub_source &lss = lnav_data.ld_log_source; bookmarks::type &bm = lss.get_user_bookmarks(); if (sqlite3_prepare_v2(db.in(), "DELETE FROM bookmarks WHERE " " log_time = ? and log_format = ? and log_hash = ? " " and session_time = ?", -1, stmt.out(), NULL) != SQLITE_OK) { fprintf(stderr, "error: could not prepare bookmark delete statemnt -- %s\n", sqlite3_errmsg(db)); return; } for (std::vector::iterator cl_iter = marked_session_lines.begin(); cl_iter != marked_session_lines.end(); ++cl_iter) { if (!bind_line( db.in(), stmt.in(), *cl_iter, lnav_data.ld_session_time)) { continue; } if (sqlite3_step(stmt.in()) != SQLITE_DONE) { fprintf(stderr, "error: could not execute bookmark insert statement -- %s\n", sqlite3_errmsg(db)); return; } sqlite3_reset(stmt.in()); } marked_session_lines.clear(); if (sqlite3_prepare_v2(db.in(), "REPLACE INTO bookmarks" " (log_time, log_format, log_hash, session_time, part_name)" " VALUES (?, ?, ?, ?, ?)", -1, stmt.out(), NULL) != SQLITE_OK) { fprintf(stderr, "error: could not prepare bookmark replace statemnt -- %s\n", sqlite3_errmsg(db)); return; } { logfile_sub_source::iterator file_iter; for (file_iter = lnav_data.ld_log_source.begin(); file_iter != lnav_data.ld_log_source.end(); ++file_iter) { logfile *lf = file_iter->ld_file; content_line_t base_content_line; if (lf == NULL) continue; base_content_line = lss.get_file_base_content_line(file_iter); base_content_line = content_line_t( base_content_line + lf->size() - 1); if (!bind_line(db.in(), stmt.in(), base_content_line, lnav_data.ld_session_time)) { continue; } if (sqlite3_bind_null(stmt.in(), 5) != SQLITE_OK) { fprintf(stderr, "error: could not bind log hash -- %s\n", sqlite3_errmsg(db.in())); return; } if (sqlite3_step(stmt.in()) != SQLITE_DONE) { fprintf(stderr, "error: could not execute bookmark insert statement -- %s\n", sqlite3_errmsg(db)); return; } sqlite3_reset(stmt.in()); } } save_user_bookmarks(db.in(), stmt.in(), bm[&textview_curses::BM_USER]); save_user_bookmarks(db.in(), stmt.in(), bm[&textview_curses::BM_PARTITION]); if (sqlite3_prepare_v2(db.in(), "DELETE FROM time_offset WHERE " " log_time = ? and log_format = ? and log_hash = ? " " and session_time = ?", -1, stmt.out(), NULL) != SQLITE_OK) { fprintf(stderr, "error: could not prepare time_offset delete statemnt -- %s\n", sqlite3_errmsg(db)); return; } for (std::vector::iterator cl_iter = offset_session_lines.begin(); cl_iter != offset_session_lines.end(); ++cl_iter) { if (!bind_line( db.in(), stmt.in(), *cl_iter, lnav_data.ld_session_time)) { continue; } if (sqlite3_step(stmt.in()) != SQLITE_DONE) { fprintf(stderr, "error: could not execute bookmark insert statement -- %s\n", sqlite3_errmsg(db)); return; } sqlite3_reset(stmt.in()); } offset_session_lines.clear(); if (sqlite3_prepare_v2(db.in(), "REPLACE INTO time_offset" " (log_time, log_format, log_hash, session_time, offset_sec, offset_usec)" " VALUES (?, ?, ?, ?, ?, ?)", -1, stmt.out(), NULL) != SQLITE_OK) { fprintf(stderr, "error: could not prepare time_offset replace statemnt -- %s\n", sqlite3_errmsg(db)); return; } { logfile_sub_source::iterator file_iter; for (file_iter = lnav_data.ld_log_source.begin(); file_iter != lnav_data.ld_log_source.end(); ++file_iter) { logfile *lf = file_iter->ld_file; content_line_t base_content_line; if (lf == NULL) continue; base_content_line = lss.get_file_base_content_line(file_iter); if (!bind_line(db.in(), stmt.in(), base_content_line, lnav_data.ld_session_time)) { continue; } if (sqlite3_bind_null(stmt.in(), 5) != SQLITE_OK) { fprintf(stderr, "error: could not bind log hash -- %s\n", sqlite3_errmsg(db.in())); return; } if (sqlite3_bind_null(stmt.in(), 6) != SQLITE_OK) { fprintf(stderr, "error: could not bind log hash -- %s\n", sqlite3_errmsg(db.in())); return; } if (sqlite3_step(stmt.in()) != SQLITE_DONE) { fprintf(stderr, "error: could not execute bookmark insert statement -- %s\n", sqlite3_errmsg(db)); return; } sqlite3_reset(stmt.in()); } } for (logfile_sub_source::iterator file_iter = lss.begin(); file_iter != lss.end(); ++file_iter) { logfile::iterator line_iter; if (file_iter->ld_file == NULL) continue; logfile *lf = file_iter->ld_file; if (!lf->is_time_adjusted()) continue; line_iter = lf->begin() + lf->get_time_offset_line(); char timestamp[64]; sql_strftime(timestamp, sizeof(timestamp), lf->original_line_time(line_iter), 'T'); if (sqlite3_bind_text(stmt.in(), 1, timestamp, strlen(timestamp), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind log time -- %s\n", sqlite3_errmsg(db.in())); return; } const std::string &format_name = lf->get_format()->get_name(); if (sqlite3_bind_text(stmt.in(), 2, format_name.c_str(), format_name.length(), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind log format -- %s\n", sqlite3_errmsg(db.in())); return; } std::string line_hash = hash_string(lf->read_line(line_iter)); if (sqlite3_bind_text(stmt.in(), 3, line_hash.c_str(), line_hash.length(), SQLITE_TRANSIENT) != SQLITE_OK) { fprintf(stderr, "error: could not bind log hash -- %s\n", sqlite3_errmsg(db.in())); return; } if (sqlite3_bind_int64(stmt.in(), 4, lnav_data.ld_session_time) != SQLITE_OK) { fprintf(stderr, "error: could not bind session time -- %s\n", sqlite3_errmsg(db.in())); return; } struct timeval offset = lf->get_time_offset(); if (sqlite3_bind_int64(stmt.in(), 5, offset.tv_sec) != SQLITE_OK) { fprintf(stderr, "error: could not bind offset_sec -- %s\n", sqlite3_errmsg(db.in())); return; } if (sqlite3_bind_int64(stmt.in(), 6, offset.tv_usec) != SQLITE_OK) { fprintf(stderr, "error: could not bind offset_usec -- %s\n", sqlite3_errmsg(db.in())); return; } if (sqlite3_step(stmt.in()) != SQLITE_DONE) { fprintf(stderr, "error: could not execute bookmark insert statement -- %s\n", sqlite3_errmsg(db)); return; } sqlite3_reset(stmt.in()); } if (sqlite3_exec(db.in(), "COMMIT", NULL, NULL, errmsg.out()) != SQLITE_OK) { fprintf(stderr, "error: unable to begin transaction -- %s\n", errmsg.in()); return; } if (sqlite3_exec(db.in(), BOOKMARK_LRU_STMT, NULL, NULL, errmsg.out()) != SQLITE_OK) { fprintf(stderr, "error: unable to delete old bookmarks -- %s\n", errmsg.in()); return; } } void save_session(void) { string view_file_name, view_file_tmp_name; auto_mem file(fclose); char view_base_name[256]; yajl_gen handle = NULL; save_time_bookmarks(); /* TODO: save the last search query */ snprintf(view_base_name, sizeof(view_base_name), "view-info-%s.ts%ld.ppid%d.json", lnav_data.ld_session_id.c_str(), lnav_data.ld_session_time, getppid()); view_file_name = dotlnav_path(view_base_name); view_file_tmp_name = view_file_name + ".tmp"; if ((file = fopen(view_file_tmp_name.c_str(), "w")) == NULL) { perror("Unable to open session file"); } else if ((handle = yajl_gen_alloc(NULL)) == NULL) { perror("Unable to create yajl_gen object"); } else { yajl_gen_config(handle, yajl_gen_beautify, 1); yajl_gen_config(handle, yajl_gen_print_callback, yajl_writer, file.in()); { yajlpp_map root_map(handle); root_map.gen("save-time"); root_map.gen((long long)time(NULL)); root_map.gen("time-offset"); root_map.gen(lnav_data.ld_log_source.is_time_offset_enabled()); root_map.gen("files"); { yajlpp_array file_list(handle); for_each(lnav_data.ld_file_names.begin(), lnav_data.ld_file_names.end(), object_field(file_list.gen, &pair::first)); } root_map.gen("views"); { yajlpp_map top_view_map(handle); for (int lpc = 0; lpc < LNV__MAX; lpc++) { textview_curses &tc = lnav_data.ld_views[lpc]; unsigned long width; vis_line_t height; top_view_map.gen(lnav_view_strings[lpc]); yajlpp_map view_map(handle); view_map.gen("top_line"); tc.get_dimensions(height, width); if (tc.get_top() >= tc.get_top_for_last_row()) { view_map.gen(-1LL); } else{ view_map.gen((long long)tc.get_top()); } view_map.gen("search"); view_map.gen(lnav_data.ld_last_search[lpc]); view_map.gen("word_wrap"); view_map.gen(tc.get_word_wrap()); } } root_map.gen("commands"); { filter_stack_t::const_iterator filter_iter; logfile_sub_source &lss = lnav_data.ld_log_source; const filter_stack_t &fs = lss.get_filters(); yajlpp_array cmd_array(handle); for (filter_iter = fs.begin(); filter_iter != fs.end(); ++filter_iter) { if (!(*filter_iter)->is_enabled()) { continue; } cmd_array.gen((*filter_iter)->to_command()); } textview_curses::highlight_map_t &hmap = lnav_data.ld_views[LNV_LOG].get_highlights(); textview_curses::highlight_map_t::iterator hl_iter; for (hl_iter = hmap.begin(); hl_iter != hmap.end(); ++hl_iter) { if (hl_iter->first[0] == '$') { continue; } cmd_array.gen("highlight " + hl_iter->first); } } } yajl_gen_clear(handle); yajl_gen_free(handle); fclose(file.release()); rename(view_file_tmp_name.c_str(), view_file_name.c_str()); } } void reset_session(void) { textview_curses::highlight_map_t &hmap = lnav_data.ld_views[LNV_LOG].get_highlights(); textview_curses::highlight_map_t::iterator hl_iter = hmap.begin(); logfile_sub_source &lss = lnav_data.ld_log_source; log_info("reset session: time=%d", lnav_data.ld_session_time); save_session(); scan_sessions(); lnav_data.ld_session_time = time(NULL); while (hl_iter != hmap.end()) { if (hl_iter->first[0] == '$') { ++hl_iter; } else { hmap.erase(hl_iter++); } } lnav_data.ld_log_source.clear_filters(); logfile_sub_source::iterator file_iter; for (file_iter = lnav_data.ld_log_source.begin(); file_iter != lnav_data.ld_log_source.end(); ++file_iter) { logfile *lf = file_iter->ld_file; lf->clear_time_offset(); } lss.get_user_bookmarks()[&textview_curses::BM_USER].clear(); lss.get_user_bookmarks()[&textview_curses::BM_PARTITION].clear(); } lnav-0.7.0/src/session_data.hh000664 000765 000024 00000003331 12211635054 016513 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file session_data.hh */ #ifndef _session_data_hh #define _session_data_hh void init_session(void); void load_session(void); void save_session(void); void reset_session(void); void scan_sessions(void); #endif lnav-0.7.0/src/shared_buffer.cc000644 000765 000024 00000005237 12312020654 016625 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file shared_buffer.cc */ #include "config.h" #ifdef HAVE_EXECINFO_H #include #endif #include "shared_buffer.hh" static const bool DEBUG_TRACE = false; void shared_buffer_ref::share(shared_buffer &sb, char *data, size_t len) { #ifdef HAVE_EXECINFO_H if (DEBUG_TRACE) { void *frames[128]; int rc; rc = backtrace(frames, 128); this->sb_backtrace.reset(backtrace_symbols(frames, rc)); } #endif this->disown(); sb.add_ref(*this); this->sb_owner = &sb; this->sb_data = data; this->sb_length = len; } bool shared_buffer_ref::subset(shared_buffer_ref &other, off_t offset, size_t len) { this->disown(); if (offset != -1) { this->sb_owner = other.sb_owner; this->sb_length = len; if (this->sb_owner == NULL) { if ((this->sb_data = (char *)malloc(this->sb_length)) == NULL) { return false; } memcpy(this->sb_data, &other.sb_data[offset], len); } else { LIST_INSERT_HEAD(&this->sb_owner->sb_refs, this, sb_link); this->sb_data = &other.sb_data[offset]; } } return true; } lnav-0.7.0/src/shared_buffer.hh000664 000765 000024 00000012143 12310243147 016635 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file shared_buffer.hh */ #ifndef __shared_buffer_hh #define __shared_buffer_hh #include #include #include #include #include "auto_mem.hh" #include "lnav_log.hh" class shared_buffer; struct shared_buffer_ref { public: shared_buffer_ref(char *data = NULL, size_t len = 0) : sb_owner(NULL), sb_data(data), sb_length(len) { }; ~shared_buffer_ref() { this->disown(); }; shared_buffer_ref(const shared_buffer_ref &other) { this->sb_owner = NULL; this->sb_data = NULL; this->sb_length = 0; this->copy_ref(other); }; shared_buffer_ref &operator=(const shared_buffer_ref &other) { if (this != &other) { this->disown(); this->copy_ref(other); } return *this; }; const char *get_data() const { return this->sb_data; }; size_t length() const { return this->sb_length; }; char *get_writable_data() { if (this->take_ownership()) { return this->sb_data; } return NULL; }; void share(shared_buffer &sb, char *data, size_t len); bool subset(shared_buffer_ref &other, off_t offset, size_t len); bool take_ownership() { if (this->sb_owner != NULL && this->sb_data != NULL) { char *new_data; if ((new_data = (char *)malloc(this->sb_length)) == NULL) { return false; } memcpy(new_data, this->sb_data, this->sb_length); this->sb_data = new_data; LIST_REMOVE(this, sb_link); this->sb_owner = NULL; } return true; }; void disown() { if (this->sb_owner == NULL) { if (this->sb_data != NULL) { free(this->sb_data); } } else { LIST_REMOVE(this, sb_link); } this->sb_owner = NULL; this->sb_data = NULL; this->sb_length = 0; }; LIST_ENTRY(shared_buffer_ref) sb_link; private: void copy_ref(const shared_buffer_ref &other) { if (other.sb_data == NULL) { this->sb_owner = NULL; this->sb_data = NULL; this->sb_length = 0; } else if (other.sb_owner != NULL) { this->share(*other.sb_owner, other.sb_data, other.sb_length); } else { this->sb_owner = NULL; this->sb_data = (char *)malloc(other.sb_length); memcpy(this->sb_data, other.sb_data, other.sb_length); this->sb_length = other.sb_length; } } auto_mem sb_backtrace; shared_buffer *sb_owner; char *sb_data; size_t sb_length; }; class shared_buffer { public: shared_buffer() { LIST_INIT(&this->sb_refs); }; ~shared_buffer() { this->invalidate_refs(); } void add_ref(shared_buffer_ref &ref) { LIST_INSERT_HEAD(&this->sb_refs, &ref, sb_link); }; bool invalidate_refs() { shared_buffer_ref *ref; bool retval = true; for (ref = LIST_FIRST(&this->sb_refs); ref != NULL; ref = LIST_FIRST(&this->sb_refs)) { retval = retval && ref->take_ownership(); } return retval; }; LIST_HEAD(shared_buffer_head, shared_buffer_ref) sb_refs; }; struct tmp_shared_buffer { tmp_shared_buffer(const char *str, size_t len = -1) { if (len == (size_t)-1) { len = strlen(str); } this->tsb_ref.share(this->tsb_manager, (char *)str, len); }; shared_buffer tsb_manager; shared_buffer_ref tsb_ref; }; #endif lnav-0.7.0/src/spookyhash/000775 000765 000024 00000000000 12315725122 015707 5ustar00stackstaff000000 000000 lnav-0.7.0/src/sql_util.cc000664 000765 000024 00000030235 12304457003 015663 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file sql_util.cc */ #include "config.h" #include #include #include "auto_mem.hh" #include "sql_util.hh" #include "lnav_log.hh" /** * Copied from -- http://www.sqlite.org/lang_keywords.html */ const char *sql_keywords[] = { "ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS", "ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY", "CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT", "CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE", "CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE", "DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH", "ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN", "FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF", "IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER", "INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY", "LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL", "NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA", "PRIMARY", "QUERY", "RAISE", "REFERENCES", "REGEXP", "REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT", "ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP", "TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE", "UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE", NULL }; const char *sql_function_names[] = { /* http://www.sqlite.org/lang_aggfunc.html */ "avg", "count", "group_concat", "max", "min", "sum", "total", /* http://www.sqlite.org/lang_corefunc.html */ "abs", "changes", "char", "coalesce", "glob", "ifnull", "instr", "hex", "last_insert_rowid", "length", "like", "load_extension", "lower", "ltrim", "nullif", "quote", "random", "randomblob", "replace", "round", "rtrim", "soundex", "sqlite_compileoption_get", "sqlite_compileoption_used", "sqlite_source_id", "sqlite_version", "substr", "total_changes", "trim", "typeof", "unicode", "upper", "zeroblob", /* http://www.sqlite.org/lang_datefunc.html */ "date", "time", "datetime", "julianday", "strftime", NULL }; static int handle_db_list(void *ptr, int ncols, char **colvalues, char **colnames) { struct sqlite_metadata_callbacks *smc; smc = (struct sqlite_metadata_callbacks *)ptr; smc->smc_db_list[colvalues[1]] = std::vector(); return smc->smc_database_list(ptr, ncols, colvalues, colnames); } struct table_list_data { struct sqlite_metadata_callbacks *tld_callbacks; db_table_map_t::iterator * tld_iter; }; static int handle_table_list(void *ptr, int ncols, char **colvalues, char **colnames) { struct table_list_data *tld = (struct table_list_data *)ptr; (*tld->tld_iter)->second.push_back(colvalues[0]); return tld->tld_callbacks->smc_table_list(tld->tld_callbacks, ncols, colvalues, colnames); } int walk_sqlite_metadata(sqlite3 *db, struct sqlite_metadata_callbacks &smc) { auto_mem errmsg; int retval; retval = sqlite3_exec(db, "pragma collation_list", smc.smc_collation_list, &smc, errmsg.out()); if (retval != SQLITE_OK) { log_error("could not get collation list -- %s", errmsg.in()); return retval; } retval = sqlite3_exec(db, "pragma database_list", handle_db_list, &smc, errmsg.out()); if (retval != SQLITE_OK) { log_error("could not get DB list -- %s", errmsg.in()); return retval; } for (db_table_map_t::iterator iter = smc.smc_db_list.begin(); iter != smc.smc_db_list.end(); ++iter) { struct table_list_data tld = { &smc, &iter }; auto_mem query; query = sqlite3_mprintf("SELECT name,sql FROM %Q.sqlite_master " "WHERE type in ('table', 'view')", iter->first.c_str()); retval = sqlite3_exec(db, query, handle_table_list, &tld, errmsg.out()); if (retval != SQLITE_OK) { log_error("could not get table list -- %s", errmsg.in()); return retval; } for (db_table_list_t::iterator table_iter = iter->second.begin(); table_iter != iter->second.end(); ++table_iter) { auto_mem table_query; std::string &table_name = *table_iter; table_query = sqlite3_mprintf( "pragma %Q.table_info(%Q)", iter->first.c_str(), table_name.c_str()); if (table_query == NULL) { return SQLITE_NOMEM; } retval = sqlite3_exec(db, table_query, smc.smc_table_info, &smc, errmsg.out()); if (retval != SQLITE_OK) { log_error("could not get table info -- %s", errmsg.in()); return retval; } table_query = sqlite3_mprintf( "pragma %Q.foreign_key_list(%Q)", iter->first.c_str(), table_name.c_str()); if (table_query == NULL) { return SQLITE_NOMEM; } retval = sqlite3_exec(db, table_query, smc.smc_foreign_key_list, &smc, errmsg.out()); if (retval != SQLITE_OK) { log_error("could not get foreign key list -- %s", errmsg.in()); return retval; } } } return retval; } static int schema_collation_list(void *ptr, int ncols, char **colvalues, char **colnames) { return 0; } static int schema_db_list(void *ptr, int ncols, char **colvalues, char **colnames) { struct sqlite_metadata_callbacks *smc = (sqlite_metadata_callbacks *)ptr; string &schema_out = *((string *)smc->smc_userdata); auto_mem attach_sql; attach_sql = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q;\n", colvalues[2], colvalues[1]); schema_out += attach_sql; return 0; } static int schema_table_list(void *ptr, int ncols, char **colvalues, char **colnames) { struct sqlite_metadata_callbacks *smc = (sqlite_metadata_callbacks *)ptr; string &schema_out = *((string *)smc->smc_userdata); auto_mem create_sql; create_sql = sqlite3_mprintf("%s;\n", colvalues[1]); schema_out += create_sql; return 0; } static int schema_table_info(void *ptr, int ncols, char **colvalues, char **colnames) { return 0; } static int schema_foreign_key_list(void *ptr, int ncols, char **colvalues, char **colnames) { return 0; } void dump_sqlite_schema(sqlite3 *db, std::string &schema_out) { struct sqlite_metadata_callbacks schema_sql_meta_callbacks = { schema_collation_list, schema_db_list, schema_table_list, schema_table_info, schema_foreign_key_list, &schema_out }; walk_sqlite_metadata(db, schema_sql_meta_callbacks); } void attach_sqlite_db(sqlite3 *db, const std::string &filename) { static pcrecpp::RE db_name_converter("[^\\w]"); auto_mem stmt(sqlite3_finalize); if (sqlite3_prepare_v2(db, "ATTACH DATABASE ? as ?", -1, stmt.out(), NULL) != SQLITE_OK) { log_error("could not prepare DB attach statement -- %s", sqlite3_errmsg(db)); return; } if (sqlite3_bind_text(stmt.in(), 1, filename.c_str(), filename.length(), SQLITE_TRANSIENT) != SQLITE_OK) { log_error("could not bind DB attach statement -- %s", sqlite3_errmsg(db)); return; } size_t base_start = filename.find_last_of("/\\"); string db_name; if (base_start == string::npos) { db_name = filename; } else { db_name = filename.substr(base_start + 1); } db_name_converter.GlobalReplace("_", &db_name); if (sqlite3_bind_text(stmt.in(), 2, db_name.c_str(), db_name.length(), SQLITE_TRANSIENT) != SQLITE_OK) { log_error("could not bind DB attach statement -- %s", sqlite3_errmsg(db)); return; } if (sqlite3_step(stmt.in()) != SQLITE_DONE) { log_error("could not execute DB attach statement -- %s", sqlite3_errmsg(db)); return; } } void sql_strftime(char *buffer, size_t buffer_size, time_t time, int millis, char sep) { struct tm gmtm; gmtime_r(&time, &gmtm); snprintf(buffer, buffer_size, "%4d-%02d-%02d%c%02d:%02d:%02d.%03d", gmtm.tm_year + 1900, gmtm.tm_mon + 1, gmtm.tm_mday, sep, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, millis); } lnav-0.7.0/src/sql_util.hh000664 000765 000024 00000005421 12302670751 015701 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file sql_util.hh */ #ifndef _sql_util_hh #define _sql_util_hh #include #include #include #include #include #include extern const char *sql_keywords[]; extern const char *sql_function_names[]; typedef int (*sqlite_exec_callback)(void *, int, char **, char **); typedef std::vector db_table_list_t; typedef std::map db_table_map_t; struct sqlite_metadata_callbacks { sqlite_exec_callback smc_collation_list; sqlite_exec_callback smc_database_list; sqlite_exec_callback smc_table_list; sqlite_exec_callback smc_table_info; sqlite_exec_callback smc_foreign_key_list; void *smc_userdata; db_table_map_t smc_db_list; }; int walk_sqlite_metadata(sqlite3 *db, struct sqlite_metadata_callbacks &smc); void dump_sqlite_schema(sqlite3 *db, std::string &schema_out); void attach_sqlite_db(sqlite3 *db, const std::string &filename); void sql_strftime(char *buffer, size_t buffer_size, time_t time, int millis, char sep = ' '); inline void sql_strftime(char *buffer, size_t buffer_size, const struct timeval &tv, char sep = ' ') { sql_strftime(buffer, buffer_size, tv.tv_sec, tv.tv_usec / 1000, sep); } #endif lnav-0.7.0/src/sqlite-extension-func.c000664 000765 000024 00000007157 12211635054 020140 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file sqlite-extension-func.c */ #include "config.h" #include #include #include "sqlite-extension-func.h" sqlite_registration_func_t sqlite_registration_funcs[] = { common_extension_functions, state_extension_functions, string_extension_functions, network_extension_functions, fs_extension_functions, NULL }; int register_sqlite_funcs(sqlite3 *db, sqlite_registration_func_t *reg_funcs) { int lpc; assert(db != NULL); assert(reg_funcs != NULL); for (lpc = 0; reg_funcs[lpc]; lpc++) { const struct FuncDef *basic_funcs = NULL; const struct FuncDefAgg *agg_funcs = NULL; int i; reg_funcs[lpc](&basic_funcs, &agg_funcs); for (i = 0; basic_funcs && basic_funcs[i].zName; i++) { void *pArg = 0; switch (basic_funcs[i].argType) { case 1: pArg = db; break; case 2: pArg = (void *)(-1); break; } //sqlite3CreateFunc /* LMH no error checking */ sqlite3_create_function(db, basic_funcs[i].zName, basic_funcs[i].nArg, basic_funcs[i].eTextRep, pArg, basic_funcs[i].xFunc, 0, 0); } for (i = 0; agg_funcs && agg_funcs[i].zName; i++) { void *pArg = 0; switch (agg_funcs[i].argType) { case 1: pArg = db; break; case 2: pArg = (void *)(-1); break; } //sqlite3CreateFunc sqlite3_create_function(db, agg_funcs[i].zName, agg_funcs[i].nArg, SQLITE_UTF8, pArg, 0, agg_funcs[i].xStep, agg_funcs[i].xFinalize); } } return 0; } lnav-0.7.0/src/sqlite-extension-func.h000664 000765 000024 00000006234 12211635054 020140 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file sqlite-extension-func.h */ #ifndef _sqlite_extension_func_h #define _sqlite_extension_func_h #include #include #ifdef __cplusplus extern "C" { #endif struct FuncDef { const char *zName; signed char nArg; uint8_t argType; /* 0: none. 1: db 2: (-1) */ uint8_t eTextRep; /* 1: UTF-16. 0: UTF-8 */ uint8_t needCollSeq; void (*xFunc)(sqlite3_context*,int,sqlite3_value **); }; struct FuncDefAgg { const char *zName; signed char nArg; uint8_t argType; uint8_t needCollSeq; void (*xStep)(sqlite3_context*,int,sqlite3_value**); void (*xFinalize)(sqlite3_context*); }; typedef int (*sqlite_registration_func_t)(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs); int common_extension_functions(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs); int state_extension_functions(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs); int string_extension_functions(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs); int network_extension_functions(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs); int fs_extension_functions(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs); extern sqlite_registration_func_t sqlite_registration_funcs[]; int register_sqlite_funcs(sqlite3 *db, sqlite_registration_func_t *reg_funcs); #ifdef __cplusplus } #endif #endif lnav-0.7.0/src/state-extension-functions.cc000664 000765 000024 00000005421 12306075067 021176 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file state-extension-functions.cc */ #include #include #include #include #include #include "sqlite3.h" #include "lnav.hh" #include "lnav_log.hh" #include "sql_util.hh" #include "sqlite-extension-func.h" static void sql_log_top_line(sqlite3_context *context, int argc, sqlite3_value **argv) { sqlite3_result_int64(context, (int64_t)lnav_data.ld_views[LNV_LOG].get_top()); } static void sql_log_top_datetime(sqlite3_context *context, int argc, sqlite3_value **argv) { char buffer[64]; require(argc == 0); sql_strftime(buffer, sizeof(buffer), lnav_data.ld_top_time, lnav_data.ld_top_time_millis); sqlite3_result_text(context, buffer, strlen(buffer), SQLITE_TRANSIENT); } int state_extension_functions(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs) { static const struct FuncDef datetime_funcs[] = { { "log_top_line", 0, 0, SQLITE_UTF8, 0, sql_log_top_line }, { "log_top_datetime", 0, 0, SQLITE_UTF8, 0, sql_log_top_datetime }, { NULL } }; *basic_funcs = datetime_funcs; return SQLITE_OK; } lnav-0.7.0/src/status_controllers.hh000664 000765 000024 00000003216 12211635054 020012 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __status_controllers_hh #define __status_controllers_hh #include "listview_curses.hh" #include "statusview_curses.hh" #endif lnav-0.7.0/src/statusview_curses.cc000664 000765 000024 00000005645 12216211402 017631 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file statusview_curses.cc */ #include "config.h" #include "statusview_curses.hh" using namespace std; void statusview_curses::do_update(void) { int top, attrs, field, field_count, left = 1, right; view_colors & vc = view_colors::singleton(); unsigned long width, height; getmaxyx(this->sc_window, height, width); top = this->sc_top < 0 ? height + this->sc_top : this->sc_top; right = width; attrs = vc.attrs_for_role(view_colors::VCR_STATUS); wattron(this->sc_window, attrs); wmove(this->sc_window, top, 0); wclrtoeol(this->sc_window); whline(this->sc_window, ' ', width); wattroff(this->sc_window, attrs); field_count = this->sc_source->statusview_fields(); for (field = 0; field < field_count; field++) { status_field &sf = this->sc_source->statusview_value_for_field( field); struct line_range lr(0, sf.get_width()); attr_line_t val; int x; val = sf.get_value(); if (sf.is_right_justified()) { right -= sf.get_width(); x = right; } else { x = left; left += sf.get_width() + 1; } this->mvwattrline(this->sc_window, top, x, val, lr, sf.get_role()); } wmove(this->sc_window, top + 1, 0); } lnav-0.7.0/src/statusview_curses.hh000664 000765 000024 00000021461 12311373541 017646 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file statusview_curses.hh */ #ifndef __statusview_curses_hh #define __statusview_curses_hh #include #include #include "view_curses.hh" #include "ansi_scrubber.hh" /** * Container for individual status values. */ class status_field { public: /** * @param width The maximum width of the field in characters. * @param role The color role for this field, defaults to VCR_STATUS. */ status_field(int width = 1, view_colors::role_t role = view_colors::VCR_STATUS) : sf_width(width), sf_min_width(0), sf_right_justify(false), sf_cylon(false), sf_cylon_pos(0), sf_role(role), sf_share(0) { }; virtual ~status_field() { }; /** @param value The new value for this field. */ void set_value(std::string value) { string_attrs_t &sa = this->sf_value.get_attrs(); sa.clear(); scrub_ansi_string(value, sa); if (value.size() > this->get_width()) { if (value.size() <= 11) { value.resize(11); } else { static const std::string MIDSUB = " .. "; size_t half_width = this->get_width() / 2 - MIDSUB.size() / 2; std::string abbrev; abbrev.append(value, 0, half_width); abbrev.append(MIDSUB); abbrev.append(value, value.size() - half_width, std::string::npos); value = abbrev; } } if (this->sf_right_justify) { int padding = this->sf_width - value.size(); if (padding > 2) { value.insert(0, padding, ' '); } } this->sf_value = value; if (this->sf_cylon) { struct line_range lr(this->sf_cylon_pos, this->sf_width); sa.push_back(string_attr(lr, &view_curses::VC_STYLE, view_colors::ansi_color_pair(COLOR_WHITE, COLOR_GREEN) | A_BOLD)); this->sf_cylon_pos += 1; if (this->sf_cylon_pos > this->sf_width) { this->sf_cylon_pos = 0; } } }; /** * Set the new value for this field using a formatted string. * * @param fmt The format string. * @param ... Arguments for the format. */ void set_value(const char *fmt, ...) { char buffer[128]; va_list args; va_start(args, fmt); vsnprintf(buffer, sizeof(buffer), fmt, args); this->set_value(std::string(buffer)); va_end(args); }; void set_stitch_value(int color_pair) { string_attrs_t & sa = this->sf_value.get_attrs(); struct line_range lr(0, 1); this->sf_value.get_string() = "::"; sa.push_back(string_attr(lr, &view_curses::VC_STYLE, A_REVERSE | COLOR_PAIR(color_pair))); lr.lr_start = 1; lr.lr_end = 2; sa.push_back(string_attr(lr, &view_curses::VC_STYLE, COLOR_PAIR(color_pair))); }; /** @return The string value for this field. */ attr_line_t &get_value() { return this->sf_value; }; void right_justify(bool yes) { this->sf_right_justify = yes; }; bool is_right_justified(void) const { return this->sf_right_justify; }; void set_cylon(bool yes) { this->sf_cylon = yes; }; bool is_cylon(void) const { return this->sf_cylon; }; /** @return True if this field's value is an empty string. */ bool empty() { return this->sf_value.get_string().empty(); }; void clear() { this->sf_value.clear(); }; /** @param role The color role for this field. */ void set_role(view_colors::role_t role) { this->sf_role = role; }; /** @return The color role for this field. */ view_colors::role_t get_role() const { return this->sf_role; }; /** @param width The maximum display width, in characters. */ void set_width(int width) { this->sf_width = width; }; /** @param width The maximum display width, in characters. */ size_t get_width() const { return this->sf_width; }; /** @param width The maximum display width, in characters. */ void set_min_width(int width) { this->sf_min_width = width; }; /** @param width The maximum display width, in characters. */ size_t get_min_width() const { return this->sf_min_width; }; void set_share(int share) { this->sf_share = share; }; int get_share() const { return this->sf_share; }; protected: size_t sf_width; /*< The maximum display width, in chars. */ size_t sf_min_width; /*< The minimum display width, in chars. */ bool sf_right_justify; bool sf_cylon; size_t sf_cylon_pos; attr_line_t sf_value; /*< The value to display for this field. */ view_colors::role_t sf_role; /*< The color role for this field. */ int sf_share; }; /** * Data source for the fields to be displayed in a status view. */ class status_data_source { public: virtual ~status_data_source() { }; /** * @return The number of status_fields in this source. */ virtual size_t statusview_fields(void) = 0; /** * Callback used to get a particular field. * * @param field The index of the field to return. * @return A reference to the field at the given index. */ virtual status_field &statusview_value_for_field(int field) = 0; }; /** * A view that displays a collection of fields in a line on the display. */ class statusview_curses : public view_curses { public: statusview_curses() : sc_source(NULL), sc_window(NULL), sc_top(0) { }; virtual ~statusview_curses() { }; void set_data_source(status_data_source *src) { this->sc_source = src; }; status_data_source *get_data_source() { return this->sc_source; }; void set_top(int top) { this->sc_top = top; }; int get_top() const { return this->sc_top; }; void set_window(WINDOW *win) { this->sc_window = win; }; WINDOW *get_window() { return this->sc_window; }; void window_change(void) { int field_count = this->sc_source->statusview_fields(); int remaining, total_shares = 0; unsigned long width, height; getmaxyx(this->sc_window, height, width); remaining = width - 4; for (int field = 0; field < field_count; field++) { status_field &sf = this->sc_source->statusview_value_for_field( field); remaining -= sf.get_share() ? sf.get_min_width() : sf.get_width(); remaining -= 1; total_shares += sf.get_share(); } if (remaining < 2) { remaining = 0; } for (int field = 0; field < field_count; field++) { status_field &sf = this->sc_source->statusview_value_for_field( field); if (sf.get_share()) { int actual_width; actual_width = sf.get_min_width(); actual_width += remaining / (sf.get_share() / total_shares); sf.set_width(actual_width); } } }; void do_update(void); private: status_data_source *sc_source; WINDOW * sc_window; int sc_top; }; #endif lnav-0.7.0/src/string-extension-functions.cc000664 000765 000024 00000012145 12211635054 021356 0ustar00stackstaff000000 000000 /* * Written by Alexey Tourbin . * * The author has dedicated the code to the public domain. Anyone is free * to copy, modify, publish, use, compile, sell, or distribute the original * code, either in source code form or as a compiled binary, for any purpose, * commercial or non-commercial, and by any means. */ #include "config.h" #include #include #include #include #include #include "pcrepp.hh" #include "sqlite-extension-func.h" typedef struct { char * s; pcrecpp::RE *re; } cache_entry; #ifndef CACHE_SIZE #define CACHE_SIZE 16 #endif static pcrecpp::RE *find_re(sqlite3_context *ctx, const char *re) { static cache_entry cache[CACHE_SIZE]; int i; int found = 0; for (i = 0; i < CACHE_SIZE && cache[i].s; i++) { if (strcmp(re, cache[i].s) == 0) { found = 1; break; } } if (found) { if (i > 0) { cache_entry c = cache[i]; memmove(cache + 1, cache, i * sizeof(cache_entry)); cache[0] = c; } } else { cache_entry c; c.re = new pcrecpp::RE(re); if (!c.re->error().empty()) { char *e2 = sqlite3_mprintf("%s: %s", re, c.re->error().c_str()); sqlite3_result_error(ctx, e2, -1); sqlite3_free(e2); delete c.re; return NULL; } c.s = strdup(re); if (!c.s) { sqlite3_result_error(ctx, "strdup: ENOMEM", -1); delete c.re; return NULL; } i = CACHE_SIZE - 1; if (cache[i].s) { free(cache[i].s); assert(cache[i].re); delete cache[i].re; } memmove(cache + 1, cache, i * sizeof(cache_entry)); cache[0] = c; } return cache[0].re; } static void regexp(sqlite3_context *ctx, int argc, sqlite3_value **argv) { const char *re, *str; pcrecpp::RE *reobj; assert(argc == 2); re = (const char *)sqlite3_value_text(argv[0]); if (!re) { sqlite3_result_error(ctx, "no regexp", -1); return; } str = (const char *)sqlite3_value_text(argv[1]); if (!str) { sqlite3_result_error(ctx, "no string", -1); return; } reobj = find_re(ctx, re); if (reobj == NULL) return; { bool rc = reobj->PartialMatch(str); sqlite3_result_int(ctx, rc); return; } } static void regexp_replace(sqlite3_context *ctx, int argc, sqlite3_value **argv) { const char *re, *str, *repl; pcrecpp::RE *reobj; assert(argc == 3); str = (const char *)sqlite3_value_text(argv[0]); if (!str) { sqlite3_result_error(ctx, "no string", -1); return; } re = (const char *)sqlite3_value_text(argv[1]); if (!re) { sqlite3_result_error(ctx, "no regexp", -1); return; } repl = (const char *)sqlite3_value_text(argv[2]); if (!repl) { sqlite3_result_error(ctx, "no string", -1); return; } reobj = find_re(ctx, re); if (reobj == NULL) return; { string dest(str); reobj->GlobalReplace(repl, &dest); sqlite3_result_text(ctx, dest.c_str(), dest.length(), SQLITE_TRANSIENT); return; } } static void sql_startswith(sqlite3_context *context, int argc, sqlite3_value **argv) { const char *str_in; const char *prefix; if ((sqlite3_value_type(argv[0]) == SQLITE_NULL) || (sqlite3_value_type(argv[1]) == SQLITE_NULL)) { sqlite3_result_null(context); return; } str_in = (const char *)sqlite3_value_text(argv[0]); prefix = (const char *)sqlite3_value_text(argv[1]); if (strncmp(str_in, prefix, strlen(prefix)) == 0) sqlite3_result_int(context, 1); else sqlite3_result_int(context, 0); } static void sql_endswith(sqlite3_context *context, int argc, sqlite3_value **argv) { const char *str_in; const char *suffix; if ((sqlite3_value_type(argv[0]) == SQLITE_NULL) || (sqlite3_value_type(argv[1]) == SQLITE_NULL)) { sqlite3_result_null(context); return; } str_in = (const char *)sqlite3_value_text(argv[0]); suffix = (const char *)sqlite3_value_text(argv[1]); int str_len = strlen(str_in); int suffix_len = strlen(suffix); if (str_len < suffix_len) { sqlite3_result_int(context, 0); } else if (strcmp(&str_in[str_len - suffix_len], suffix) == 0) { sqlite3_result_int(context, 1); } else { sqlite3_result_int(context, 0); } } int string_extension_functions(const struct FuncDef **basic_funcs, const struct FuncDefAgg **agg_funcs) { static const struct FuncDef string_funcs[] = { { "regexp", 2, 0, SQLITE_UTF8, 0, regexp }, { "regexp_replace", 3, 0, SQLITE_UTF8, 0, regexp_replace }, { "startswith", 2, 0, SQLITE_UTF8, 0, sql_startswith }, { "endswith", 2, 0, SQLITE_UTF8, 0, sql_endswith }, { NULL } }; *basic_funcs = string_funcs; return SQLITE_OK; } lnav-0.7.0/src/strnatcmp.c000664 000765 000024 00000011732 12306074140 015677 0ustar00stackstaff000000 000000 /* -*- mode: c; c-file-style: "k&r" -*- strnatcmp.c -- Perform 'natural order' comparisons of strings in C. Copyright (C) 2000, 2004 by Martin Pool This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* partial change history: * * 2004-10-10 mbp: Lift out character type dependencies into macros. * * Eric Sosman pointed out that ctype functions take a parameter whose * value must be that of an unsigned int, even on platforms that have * negative chars in their default char type. */ #include #include #include #include #include "strnatcmp.h" /* These are defined as macros to make it easier to adapt this code to * different characters types or comparison functions. */ static inline int nat_isdigit(nat_char a) { return isdigit((unsigned char) a); } static inline int nat_isspace(nat_char a) { return isspace((unsigned char) a); } static inline nat_char nat_toupper(nat_char a) { return toupper((unsigned char) a); } static int compare_right(int a_len, nat_char const *a, int b_len, nat_char const *b) { int bias = 0; /* The longest run of digits wins. That aside, the greatest value wins, but we can't know that it will until we've scanned both numbers to know that they have the same magnitude, so we remember it in BIAS. */ for (;; a++, b++, a_len--, b_len--) { if (a_len == 0 && b_len == 0) return 0; if (a_len == 0) return -1; if (b_len == 0) return 1; if (!nat_isdigit(*a) && !nat_isdigit(*b)) return bias; else if (!nat_isdigit(*a)) return -1; else if (!nat_isdigit(*b)) return +1; else if (*a < *b) { if (!bias) bias = -1; } else if (*a > *b) { if (!bias) bias = +1; } else if (!*a && !*b) return bias; } return 0; } static int compare_left(int a_len, nat_char const *a, int b_len, nat_char const *b) { /* Compare two left-aligned numbers: the first to have a different value wins. */ for (;; a++, b++, a_len--, b_len--) { if (a_len == 0 && b_len == 0) return 0; if (a_len == 0) return -1; if (b_len == 0) return 1; if (!nat_isdigit(*a) && !nat_isdigit(*b)) return 0; else if (!nat_isdigit(*a)) return -1; else if (!nat_isdigit(*b)) return +1; else if (*a < *b) return -1; else if (*a > *b) return +1; } return 0; } static int strnatcmp0(int a_len, nat_char const *a, int b_len, nat_char const *b, int fold_case) { int ai, bi; nat_char ca, cb; int fractional, result; assert(a && b); ai = bi = 0; while (1) { if (ai >= a_len) ca = 0; else ca = a[ai]; if (bi >= b_len) cb = 0; else cb = b[bi]; /* skip over leading spaces or zeros */ while (nat_isspace(ca)) { ai += 1; if (ai >= a_len) ca = 0; else ca = a[ai]; } while (nat_isspace(cb)) { bi += 1; if (bi >= b_len) cb = 0; else cb = b[bi]; } /* process run of digits */ if (nat_isdigit(ca) && nat_isdigit(cb)) { fractional = (ca == '0' || cb == '0'); if (fractional) { if ((result = compare_left(a_len - ai, a+ai, b_len - bi, b+bi)) != 0) return result; } else { if ((result = compare_right(a_len - ai, a+ai, b_len - bi, b+bi)) != 0) return result; } } if (!ca && !cb) { /* The strings compare the same. Perhaps the caller will want to call strcmp to break the tie. */ return 0; } if (fold_case) { ca = nat_toupper(ca); cb = nat_toupper(cb); } if (ca < cb) return -1; else if (ca > cb) return +1; ++ai; ++bi; } } int strnatcmp(int a_len, nat_char const *a, int b_len, nat_char const *b) { return strnatcmp0(a_len, a, b_len, b, 0); } /* Compare, recognizing numeric string and ignoring case. */ int strnatcasecmp(int a_len, nat_char const *a, int b_len, nat_char const *b) { return strnatcmp0(a_len, a, b_len, b, 1); } lnav-0.7.0/src/strnatcmp.h000664 000765 000024 00000002463 12211635054 015707 0ustar00stackstaff000000 000000 /* -*- mode: c; c-file-style: "k&r" -*- strnatcmp.c -- Perform 'natural order' comparisons of strings in C. Copyright (C) 2000, 2004 by Martin Pool This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* CUSTOMIZATION SECTION * * You can change this typedef, but must then also change the inline * functions in strnatcmp.c */ typedef char nat_char; int strnatcmp(int a_len, nat_char const *a, int b_len, nat_char const *b); int strnatcasecmp(int a_len, nat_char const *a, int b_len, nat_char const *b); lnav-0.7.0/src/strong_int.hh000664 000765 000024 00000006674 12307465165 016254 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file strong_int.hh */ #ifndef __strong_int_hh #define __strong_int_hh /** * Template class for "strongly-typed" integers, in other words, integers that * have different semantic meaning and cannot be easily used in place of one * another. * * @param T The integer type. * @param DISTINCT An class used solely to distinguish templates that have the * same integer type. */ template class strong_int { public: explicit strong_int(T v = 0) : value(v) { }; operator const T &() const { return this->value; }; strong_int operator+(const strong_int &rhs) { return strong_int(this->value + rhs.value); }; strong_int operator-(const strong_int &rhs) { return strong_int(this->value - rhs.value); }; strong_int operator/(const strong_int &rhs) { return strong_int(this->value / rhs.value); }; bool operator<(const strong_int &rhs) const { return this->value < rhs.value; }; strong_int &operator+=(const strong_int &rhs) { this->value += rhs.value; return *this; }; strong_int &operator-=(const strong_int &rhs) { this->value -= rhs.value; return *this; }; strong_int &operator-(void) { this->value = -this->value; return *this; }; strong_int &operator++(void) { this->value++; return *this; }; strong_int &operator--(void) { this->value--; return *this; }; bool operator==(const strong_int &rhs) const { return this->value == rhs.value; }; T *out(void) { return &this->value; }; private: T value; }; /** * Macro that declares a strongly-typed integer and the empty class used as a * distinguisher. * * @param T The integer type. * @param name The name of the strongly-typed integer. */ #define STRONG_INT_TYPE(T, name) \ class __ ## name ## _distinct; \ typedef strong_int name ## _t #endif lnav-0.7.0/src/term_extra.hh000664 000765 000024 00000007577 12304464204 016231 0ustar00stackstaff000000 000000 /** * Copyright (c) 2014, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file term_extra.hh */ #ifndef __term_extra_hh #define __term_extra_hh #include #include #include #include #include #include #include "logfile.hh" #include "log_format.hh" #include "listview_curses.hh" class term_extra { public: typedef listview_curses::action::mem_functor_t lv_functor_t; lv_functor_t filename_wire; term_extra() : filename_wire(*this, &term_extra::update_title) { const char *term_name = getenv("TERM"); this->te_enabled = (term_name != NULL && strstr(term_name, "xterm") != NULL); if (getenv("SSH_CONNECTION") != NULL) { char hostname[MAXHOSTNAMELEN] = "UNKNOWN"; struct passwd *userent; gethostname(hostname, sizeof(hostname)); this->te_prefix = hostname; if ((userent = getpwuid(getuid())) != NULL) { this->te_prefix = std::string(userent->pw_name) + "@" + this->te_prefix; } this->te_prefix += ":"; } }; void update_title(listview_curses *lc) { static const char *xterm_title_fmt = "\033]0;%s\007"; if (!this->te_enabled) { return; } if (lc->get_inner_height() > 0) { string_attrs_t::const_iterator line_attr; attr_line_t al; lc->get_data_source()->listview_value_for_row(*lc, lc->get_top(), al); string_attrs_t &sa = al.get_attrs(); line_attr = find_string_attr(sa, &logline::L_FILE); if (line_attr != sa.end()) { logfile *lf = (logfile *)line_attr->sa_value.sav_ptr; const std::string &filename = lf->get_filename(); if (filename != this->te_last_title) { std::string title = this->te_prefix + filename; printf(xterm_title_fmt, title.c_str()); this->te_last_title = filename; } return; } } const std::string &view_title = lc->get_title(); if (view_title != this->te_last_title) { std::string title = this->te_prefix + view_title; printf(xterm_title_fmt, title.c_str()); this->te_last_title = view_title; } }; private: bool te_enabled; std::string te_prefix; std::string te_last_title; }; #endif lnav-0.7.0/src/termios_guard.hh000664 000765 000024 00000005053 12304471314 016706 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file termios_guard.hh */ #ifndef __termios_guard_hh #define __termios_guard_hh #include #include #include /** * RAII class that saves the current termios for a tty and then restores them * during destruction. */ class guard_termios { public: /** * Store the TTY termios settings in this object. * * @param fd The tty file descriptor. */ guard_termios(const int fd) : gt_fd(fd) { if (isatty(this->gt_fd) && tcgetattr(this->gt_fd, &this->gt_termios) == -1) { perror("tcgetattr"); } }; /** * Restore the TTY termios settings that were captured when this object was * instantiated. */ ~guard_termios() { if (isatty(this->gt_fd) && tcsetattr(this->gt_fd, TCSANOW, &this->gt_termios) == -1) { perror("tcsetattr"); } }; const struct termios *get_termios() const { return &this->gt_termios; }; private: const int gt_fd; struct termios gt_termios; }; #endif lnav-0.7.0/src/test_override.cc000664 000765 000024 00000000256 12211635054 016706 0ustar00stackstaff000000 000000 #include "config.h" #include time_t time(time_t *loc) { time_t retval = 1370546000; if (loc != NULL) { *loc = retval; } return retval; } lnav-0.7.0/src/textfile_sub_source.hh000664 000765 000024 00000006716 12270770564 020141 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __textfile_sub_source_hh #define __textfile_sub_source_hh #include #include "logfile.hh" #include "textview_curses.hh" class textfile_sub_source : public text_sub_source { public: typedef std::list::iterator file_iterator; textfile_sub_source() { }; size_t text_line_count() { size_t retval = 0; if (!this->tss_files.empty()) { retval = this->current_file()->size(); } return retval; }; void text_value_for_line(textview_curses &tc, int line, std::string &value_out, bool raw = false) { if (!this->tss_files.empty()) { this->current_file()-> read_line(this->current_file()->begin() + line, value_out); } else { value_out.clear(); } }; void text_attrs_for_line(textview_curses &tc, int row, string_attrs_t &value_out) { if (this->current_file() == NULL) { return; } struct line_range lr; lr.lr_start = 0; lr.lr_end = -1; value_out.push_back(string_attr(lr, &logline::L_FILE, this->current_file())); }; size_t text_size_for_line(textview_curses &tc, int line, bool raw) { size_t retval = 0; if (!this->tss_files.empty()) { retval = this->current_file()->line_length(this->current_file()->begin() + line); } return retval; }; logfile *current_file(void) const { if (this->tss_files.empty()) { return NULL; } return this->tss_files.front(); }; std::string text_source_name(const textview_curses &tv) { if (this->tss_files.empty()) { return ""; } return this->tss_files.front()->get_filename(); } std::list tss_files; }; #endif lnav-0.7.0/src/textview_curses.cc000664 000765 000024 00000024213 12306346062 017275 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include "pcrepp.hh" #include "lnav_util.hh" #include "data_parser.hh" #include "ansi_scrubber.hh" #include "textview_curses.hh" using namespace std; bookmark_type_t textview_curses::BM_USER; bookmark_type_t textview_curses::BM_PARTITION; bookmark_type_t textview_curses::BM_SEARCH; string_attr_type textview_curses::SA_BODY; textview_curses::textview_curses() : tc_sub_source(NULL), tc_delegate(NULL), tc_searching(false), tc_follow_search(false), tc_selection_start(-1), tc_selection_last(-1) { this->set_data_source(this); } textview_curses::~textview_curses() { } void textview_curses::reload_data(void) { if (this->tc_sub_source != NULL) { this->tc_sub_source->text_update_marks(this->tc_bookmarks); } this->listview_curses::reload_data(); } void textview_curses::grep_begin(grep_proc &gp) { this->tc_searching = true; this->tc_search_action.invoke(this); listview_curses::reload_data(); } void textview_curses::grep_end(grep_proc &gp) { this->tc_searching = false; this->tc_search_action.invoke(this); } void textview_curses::grep_match(grep_proc &gp, grep_line_t line, int start, int end) { this->tc_bookmarks[&BM_SEARCH].insert_once(vis_line_t(line)); if (this->tc_sub_source != NULL) { this->tc_sub_source->text_mark(&BM_SEARCH, line, true); } if (this->get_top() <= line && line <= this->get_bottom()) { listview_curses::reload_data(); } } void textview_curses::listview_value_for_row(const listview_curses &lv, vis_line_t row, attr_line_t &value_out) { bookmark_vector &user_marks = this->tc_bookmarks[&BM_USER]; bookmark_vector &part_marks = this->tc_bookmarks[&BM_PARTITION]; string_attrs_t & sa = value_out.get_attrs(); string & str = value_out.get_string(); highlight_map_t::iterator iter; string::iterator str_iter; this->tc_sub_source->text_value_for_line(*this, row, str); this->tc_sub_source->text_attrs_for_line(*this, row, sa); scrub_ansi_string(str, sa); struct line_range body; body = find_string_attr_range(sa, &SA_BODY); if (body.lr_start == -1) { body.lr_start = 0; body.lr_end = str.size(); } for (iter = this->tc_highlights.begin(); iter != this->tc_highlights.end(); iter++) { // XXX testing for '$search' here sucks bool internal_hl = iter->first[0] == '$' && iter->first != "$search"; int off, hcount = 0; size_t re_end; if (body.lr_end > 8192) re_end = 8192; else re_end = body.lr_end; for (off = internal_hl ? body.lr_start : 0; off < (int)str.size(); ) { int rc, matches[60]; rc = pcre_exec(iter->second.h_code, iter->second.h_code_extra, str.c_str(), re_end, off, 0, matches, 60); if (rc > 0) { struct line_range lr; if (rc == 2) { lr.lr_start = matches[2]; lr.lr_end = matches[3]; } else { lr.lr_start = matches[0]; lr.lr_end = matches[1]; } if (lr.lr_end > lr.lr_start) { sa.push_back(string_attr( lr, &view_curses::VC_STYLE, iter->second.get_attrs(hcount))); hcount++; off = matches[1]; } else { off += 1; } } else { off = str.size(); } } } #if 0 typedef std::map key_map_t; static key_map_t key_roles; data_scanner ds(str); data_parser dp(&ds); dp.parse(); for (list::iterator iter = dp.dp_stack.begin(); iter != dp.dp_stack.end(); ++iter) { view_colors &vc = view_colors::singleton(); if (iter->e_token == DNT_PAIR) { list::iterator pair_iter; key_map_t::iterator km_iter; data_token_t value_token; struct line_range lr; string key; value_token = iter->e_sub_elements->back().e_sub_elements->front().e_token; if (value_token == DT_STRING) { continue; } lr.lr_start = iter->e_capture.c_begin; lr.lr_end = iter->e_capture.c_end; key = ds.get_input().get_substr( &iter->e_sub_elements->front().e_capture); if ((km_iter = key_roles.find(key)) == key_roles.end()) { key_roles[key] = vc.next_highlight(); } /* fprintf(stderr, "key = %s\n", key.c_str()); */ sa[lr].insert(make_string_attr("style", vc.attrs_for_role(key_roles[key]))); pair_iter = iter->e_sub_elements->begin(); ++pair_iter; lr.lr_start = pair_iter->e_capture.c_begin; lr.lr_end = pair_iter->e_capture.c_end; sa[lr].insert(make_string_attr("style", COLOR_PAIR(view_colors::VC_WHITE) | A_BOLD)); } } #endif if (binary_search(user_marks.begin(), user_marks.end(), row)) { struct line_range lr(0); string_attrs_t::iterator iter; for (iter = sa.begin(); iter != sa.end(); iter++) { if (iter->sa_type == &view_curses::VC_STYLE) { iter->sa_value.sav_int ^= A_REVERSE; } } sa.push_back(string_attr(lr, &view_curses::VC_STYLE, A_REVERSE)); } else if (binary_search(part_marks.begin(), part_marks.end(), row + 1)) { sa.push_back(string_attr( line_range(0), &view_curses::VC_STYLE, A_UNDERLINE)); } } bool textview_curses::handle_mouse(mouse_event &me) { unsigned long width; vis_line_t height; if (this->tc_selection_start == -1 && listview_curses::handle_mouse(me)) { return true; } if (this->tc_delegate != NULL && this->tc_delegate->text_handle_mouse(*this, me)) { return true; } if (me.me_button != BUTTON_LEFT) { return false; } vis_line_t mouse_line(this->get_top() + me.me_y); if (mouse_line > this->get_bottom()) { mouse_line = this->get_bottom(); } this->get_dimensions(height, width); switch (me.me_state) { case BUTTON_STATE_PRESSED: this->tc_selection_start = mouse_line; this->tc_selection_last = vis_line_t(-1); this->tc_selection_cleared = false; break; case BUTTON_STATE_DRAGGED: if (me.me_y <= 0) { this->shift_top(vis_line_t(-1)); me.me_y = 0; mouse_line = this->get_top(); } if (me.me_y >= height && this->get_top() < this->get_top_for_last_row()) { this->shift_top(vis_line_t(1)); me.me_y = height; mouse_line = this->get_bottom(); } if (this->tc_selection_last == mouse_line) break; if (this->tc_selection_last != -1) { this->toggle_user_mark(&textview_curses::BM_USER, this->tc_selection_start, this->tc_selection_last); } if (this->tc_selection_start == mouse_line) { this->tc_selection_last = vis_line_t(-1); } else { if (!this->tc_selection_cleared) { if (this->tc_sub_source != NULL) { this->tc_sub_source->text_clear_marks(&BM_USER); } this->tc_bookmarks[&BM_USER].clear(); this->tc_selection_cleared = true; } this->toggle_user_mark(&BM_USER, this->tc_selection_start, mouse_line); this->tc_selection_last = mouse_line; } this->reload_data(); break; case BUTTON_STATE_RELEASED: this->tc_selection_start = vis_line_t(-1); this->tc_selection_last = vis_line_t(-1); this->tc_selection_cleared = false; break; } return true; } lnav-0.7.0/src/textview_curses.hh000664 000765 000024 00000034714 12306254532 017316 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file textview_curses.hh */ #ifndef __textview_curses_hh #define __textview_curses_hh #include #include "grep_proc.hh" #include "bookmarks.hh" #include "listview_curses.hh" #include "lnav_log.hh" class textview_curses; /** * Source for the text to be shown in a textview_curses view. */ class text_sub_source { public: virtual ~text_sub_source() { }; virtual void toggle_scrub(void) { }; /** * @return The total number of lines available from the source. */ virtual size_t text_line_count() = 0; /** * Get the value for a line. * * @param tc The textview_curses object that is delegating control. * @param line The line number to retrieve. * @param value_out The string object that should be set to the line * contents. * @param raw Indicates that the raw contents of the line should be returned * without any post processing. */ virtual void text_value_for_line(textview_curses &tc, int line, std::string &value_out, bool raw = false) = 0; virtual size_t text_size_for_line(textview_curses &tc, int line, bool raw = false) = 0; /** * Inform the source that the given line has been marked/unmarked. This * callback function can be used to translate between between visible line * numbers and content line numbers. For example, when viewing a log file * with filters being applied, we want the bookmarked lines to be stable * across changes in the filters. * * @param bm The type of bookmark. * @param line The line that has been marked/unmarked. * @param added True if the line was bookmarked and false if it was * unmarked. */ virtual void text_mark(bookmark_type_t *bm, int line, bool added) {}; /** * Clear the bookmarks for a particular type in the text source. * * @param bm The type of bookmarks to clear. */ virtual void text_clear_marks(bookmark_type_t *bm) {}; /** * Get the attributes for a line of text. * * @param tc The textview_curses object that is delegating control. * @param line The line number to retrieve. * @param value_out A string_attrs_t object that should be updated with the * attributes for the line. */ virtual void text_attrs_for_line(textview_curses &tc, int line, string_attrs_t &value_out) {}; /** * Update the bookmarks used by the text view based on the bookmarks * maintained by the text source. * * @param bm The bookmarks data structure used by the text view. */ virtual void text_update_marks(vis_bookmarks &bm) { }; virtual std::string text_source_name(const textview_curses &tv) { return ""; }; }; class text_delegate { public: virtual ~text_delegate() { }; virtual void text_overlay(textview_curses &tc) { }; virtual bool text_handle_mouse(textview_curses &tc, mouse_event &me) { return false; }; }; /** * The textview_curses class adds user bookmarks and searching to the standard * list view interface. */ class textview_curses : public listview_curses, public list_data_source, public grep_proc_source, public grep_proc_sink { public: typedef view_action action; static bookmark_type_t BM_USER; static bookmark_type_t BM_PARTITION; static bookmark_type_t BM_SEARCH; static string_attr_type SA_BODY; struct highlighter { highlighter() : h_code(NULL), h_multiple(false) { }; highlighter(pcre *code, bool multiple = false, view_colors::role_t role = view_colors::VCR_NONE) : h_code(code), h_multiple(multiple) { const char *errptr; if (!multiple) { if (role == view_colors::VCR_NONE) { this->h_roles. push_back(view_colors::singleton().next_highlight()); } else { this->h_roles.push_back(role); } } this->h_code_extra = pcre_study(this->h_code, 0, &errptr); if (!this->h_code_extra && errptr) { log_error("pcre_study error: %s", errptr); } if (this->h_code_extra != NULL) { pcre_extra *extra = this->h_code_extra; extra->flags |= (PCRE_EXTRA_MATCH_LIMIT | PCRE_EXTRA_MATCH_LIMIT_RECURSION); extra->match_limit = 10000; extra->match_limit_recursion = 500; } }; view_colors::role_t get_role(unsigned int index) { view_colors & vc = view_colors::singleton(); view_colors::role_t retval; if (this->h_multiple) { while (index >= this->h_roles.size()) { this->h_roles.push_back(vc.next_highlight()); } retval = this->h_roles[index]; } else { retval = this->h_roles[0]; } return retval; }; int get_attrs(int index) { return view_colors::singleton(). attrs_for_role(this->get_role(index)); }; pcre * h_code; pcre_extra * h_code_extra; bool h_multiple; std::vector h_roles; }; textview_curses(); virtual ~textview_curses(); vis_bookmarks &get_bookmarks(void) { return this->tc_bookmarks; }; void toggle_user_mark(bookmark_type_t *bm, vis_line_t start_line, vis_line_t end_line = vis_line_t(-1)) { if (end_line == -1) { end_line = start_line; } if (start_line > end_line) { std::swap(start_line, end_line); } for (vis_line_t curr_line = start_line; curr_line <= end_line; ++curr_line) { bookmark_vector &bv = this->tc_bookmarks[bm]; bookmark_vector::iterator iter; bool added; iter = bv.insert_once(curr_line); if (iter == bv.end()) { added = true; } else { bv.erase(iter); added = false; } if (this->tc_sub_source != NULL) { this->tc_sub_source->text_mark(bm, (int)curr_line, added); } } }; void set_user_mark(bookmark_type_t *bm, vis_line_t vl, bool marked) { bookmark_vector &bv = this->tc_bookmarks[bm]; bookmark_vector::iterator iter; if (marked) { bv.insert_once(vl); } else { iter = std::lower_bound(bv.begin(), bv.end(), vl); if (iter != bv.end() && *iter == vl) { bv.erase(iter); } } if (this->tc_sub_source != NULL) { this->tc_sub_source->text_mark(bm, (int)vl, marked); } }; void set_sub_source(text_sub_source *src) { this->tc_sub_source = src; this->reload_data(); }; text_sub_source *get_sub_source(void) const { return this->tc_sub_source; }; void set_delegate(text_delegate *del) { this->tc_delegate = del; }; text_delegate *get_delegate(void) const { return this->tc_delegate; }; void horiz_shift(vis_line_t start, vis_line_t end, int off_start, std::string highlight_name, std::pair &range_out) { highlighter &hl = this->tc_highlights[highlight_name]; int prev_hit = -1, next_hit = INT_MAX; std::string str; for (; start < end; ++start) { int off; this->tc_sub_source->text_value_for_line(*this, start, str); for (off = 0; off < (int)str.size(); ) { int rc, matches[128]; rc = pcre_exec(hl.h_code, hl.h_code_extra, str.c_str(), str.size(), off, 0, matches, 128); if (rc > 0) { struct line_range lr; if (rc == 2) { lr.lr_start = matches[2]; lr.lr_end = matches[3]; } else { lr.lr_start = matches[0]; lr.lr_end = matches[1]; } if (lr.lr_start < off_start) { prev_hit = std::max(prev_hit, lr.lr_start); } else if (lr.lr_start > off_start) { next_hit = std::min(next_hit, lr.lr_start); } if (lr.lr_end > lr.lr_start) { off = matches[1]; } else { off += 1; } } else { off = str.size(); } } } range_out = std::make_pair(prev_hit, next_hit); }; void set_search_action(action sa) { this->tc_search_action = sa; }; template void set_search_action(action::mem_functor_t<_Receiver> *mf) { this->tc_search_action = action(mf); }; void grep_end_batch(grep_proc &gp) { if (this->tc_follow_search && !this->tc_bookmarks[&BM_SEARCH].empty()) { vis_line_t first_hit; first_hit = this->tc_bookmarks[&BM_SEARCH]. next(vis_line_t(this->get_top() - 1)); if (first_hit != -1) { if (first_hit > 0) { --first_hit; } this->set_top(first_hit); } } this->tc_search_action.invoke(this); }; void grep_end(grep_proc &gp); size_t listview_rows(const listview_curses &lv) { return this->tc_sub_source == NULL ? 0 : this->tc_sub_source->text_line_count(); }; void listview_value_for_row(const listview_curses &lv, vis_line_t line, attr_line_t &value_out); size_t listview_size_for_row(const listview_curses &lv, vis_line_t row) { return this->tc_sub_source->text_size_for_line(*this, row); }; std::string listview_source_name(const listview_curses &lv) { return this->tc_sub_source == NULL ? "" : this->tc_sub_source->text_source_name(*this); }; bool grep_value_for_line(int line, std::string &value_out) { bool retval = false; if (this->tc_sub_source != NULL && line < (int)this->tc_sub_source->text_line_count()) { this->tc_sub_source->text_value_for_line(*this, line, value_out, true); retval = true; } return retval; }; void grep_begin(grep_proc &gp); void grep_match(grep_proc &gp, grep_line_t line, int start, int end); bool is_searching(void) { return this->tc_searching; }; void set_follow_search(bool fs) { this->tc_follow_search = fs; }; size_t get_match_count(void) { return this->tc_bookmarks[&BM_SEARCH].size(); }; void match_reset() { this->tc_bookmarks[&BM_SEARCH].clear(); if (this->tc_sub_source != NULL) { this->tc_sub_source->text_clear_marks(&BM_SEARCH); } }; typedef std::map highlight_map_t; highlight_map_t &get_highlights() { return this->tc_highlights; }; bool handle_mouse(mouse_event &me); void reload_data(void); void do_update(void) { this->listview_curses::do_update(); if (this->tc_delegate != NULL) { this->tc_delegate->text_overlay(*this); } }; protected: text_sub_source *tc_sub_source; text_delegate *tc_delegate; vis_bookmarks tc_bookmarks; vis_line_t tc_lview_top; int tc_lview_left; bool tc_searching; bool tc_follow_search; action tc_search_action; highlight_map_t tc_highlights; highlight_map_t::iterator tc_current_highlight; vis_line_t tc_selection_start; vis_line_t tc_selection_last; bool tc_selection_cleared; }; #endif lnav-0.7.0/src/time_fmts.cc000664 000765 000024 00000024666 12315724154 016037 0ustar00stackstaff000000 000000 #include #include #include "ptimec.hh" bool ptime_f1(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_Y(dst, str, off, len)) return false; if (!ptime_char('-', str, off, len)) return false; if (!ptime_m(dst, str, off, len)) return false; if (!ptime_char('-', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f2(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_Y(dst, str, off, len)) return false; if (!ptime_char('-', str, off, len)) return false; if (!ptime_m(dst, str, off, len)) return false; if (!ptime_char('-', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f3(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_Y(dst, str, off, len)) return false; if (!ptime_char('-', str, off, len)) return false; if (!ptime_m(dst, str, off, len)) return false; if (!ptime_char('-', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char('T', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f4(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_Y(dst, str, off, len)) return false; if (!ptime_char('-', str, off, len)) return false; if (!ptime_m(dst, str, off, len)) return false; if (!ptime_char('-', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char('T', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; if (!ptime_char('Z', str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f5(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_Y(dst, str, off, len)) return false; if (!ptime_char('/', str, off, len)) return false; if (!ptime_m(dst, str, off, len)) return false; if (!ptime_char('/', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f6(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_Y(dst, str, off, len)) return false; if (!ptime_char('/', str, off, len)) return false; if (!ptime_m(dst, str, off, len)) return false; if (!ptime_char('/', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f7(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_upto(' ', str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_b(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_Y(dst, str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f8(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_upto(' ', str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_b(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_upto(' ', str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_Y(dst, str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f9(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_upto(' ', str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_b(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f10(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char('/', str, off, len)) return false; if (!ptime_b(dst, str, off, len)) return false; if (!ptime_char('/', str, off, len)) return false; if (!ptime_Y(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_z(dst, str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f11(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_b(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f12(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_m(dst, str, off, len)) return false; if (!ptime_char('/', str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char('/', str, off, len)) return false; if (!ptime_y(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; return true; } #include #include #include "ptimec.hh" bool ptime_f13(struct tm *dst, const char *str, off_t &off, size_t len) { if (!ptime_m(dst, str, off, len)) return false; if (!ptime_d(dst, str, off, len)) return false; if (!ptime_char(' ', str, off, len)) return false; if (!ptime_H(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_M(dst, str, off, len)) return false; if (!ptime_char(':', str, off, len)) return false; if (!ptime_S(dst, str, off, len)) return false; return true; } struct ptime_fmt PTIMEC_FORMATS[] = { { "%Y-%m-%d %H:%M:%S", ptime_f1 }, { "%Y-%m-%d %H:%M", ptime_f2 }, { "%Y-%m-%dT%H:%M:%S", ptime_f3 }, { "%Y-%m-%dT%H:%M:%SZ", ptime_f4 }, { "%Y/%m/%d %H:%M:%S", ptime_f5 }, { "%Y/%m/%d %H:%M", ptime_f6 }, { "%a %b %d %H:%M:%S %Y", ptime_f7 }, { "%a %b %d %H:%M:%S %Z %Y", ptime_f8 }, { "%a %b %d %H:%M:%S ", ptime_f9 }, { "%d/%b/%Y:%H:%M:%S %z", ptime_f10 }, { "%b %d %H:%M:%S", ptime_f11 }, { "%m/%d/%y %H:%M:%S", ptime_f12 }, { "%m%d %H:%M:%S", ptime_f13 }, { NULL, NULL } }; const char *PTIMEC_FORMAT_STR[] = { "%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%dT%H:%M:%SZ", "%Y/%m/%d %H:%M:%S", "%Y/%m/%d %H:%M", "%a %b %d %H:%M:%S %Y", "%a %b %d %H:%M:%S %Z %Y", "%a %b %d %H:%M:%S ", "%d/%b/%Y:%H:%M:%S %z", "%b %d %H:%M:%S", "%m/%d/%y %H:%M:%S", "%m%d %H:%M:%S", NULL }; lnav-0.7.0/src/time_T.hh000664 000765 000024 00000004351 12211635054 015263 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __time_t_hh #define __time_t_hh #include #include #include #define timeit(_block) { \ struct timeval _st, _en, _diff; \ \ gettimeofday(&_st, NULL); \ { _block; } \ gettimeofday(&_en, NULL); \ timersub(&_en, &_st, &_diff); \ fprintf(stderr, \ "%s %d.%06d\n", \ #_block, _diff.tv_sec, _diff.tv_usec); \ fflush(stderr); \ } #endif lnav-0.7.0/src/top_status_source.hh000664 000765 000024 00000013433 12276161027 017635 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _top_status_source_hh #define _top_status_source_hh #include #include "logfile_sub_source.hh" #include "statusview_curses.hh" class top_status_source : public status_data_source { public: typedef listview_curses::action::mem_functor_t< top_status_source> lv_functor_t; typedef enum { TSF_TIME, TSF_PARTITION_NAME, TSF_VIEW_NAME, TSF_STITCH_VIEW_FORMAT, TSF_FORMAT, TSF_STITCH_FORMAT_FILENAME, TSF_FILENAME, TSF__MAX } field_t; top_status_source() : filename_wire(*this, &top_status_source::update_filename) { this->tss_fields[TSF_TIME].set_width(24); this->tss_fields[TSF_PARTITION_NAME].set_width(30); this->tss_fields[TSF_VIEW_NAME].set_width(6); this->tss_fields[TSF_VIEW_NAME].right_justify(true); this->tss_fields[TSF_STITCH_VIEW_FORMAT].set_width(2); this->tss_fields[TSF_STITCH_VIEW_FORMAT].set_stitch_value( view_colors::ansi_color_pair_index(COLOR_CYAN, COLOR_BLUE)); this->tss_fields[TSF_STITCH_VIEW_FORMAT].right_justify(true); this->tss_fields[TSF_FORMAT].set_width(13); this->tss_fields[TSF_FORMAT].right_justify(true); this->tss_fields[TSF_STITCH_FORMAT_FILENAME].set_width(2); this->tss_fields[TSF_STITCH_FORMAT_FILENAME].set_stitch_value( view_colors::ansi_color_pair_index(COLOR_WHITE, COLOR_CYAN)); this->tss_fields[TSF_STITCH_FORMAT_FILENAME].right_justify(true); this->tss_fields[TSF_FILENAME].set_min_width(35); /* XXX */ this->tss_fields[TSF_FILENAME].set_share(1); this->tss_fields[TSF_FILENAME].right_justify(true); }; lv_functor_t filename_wire; size_t statusview_fields(void) { return TSF__MAX; }; status_field &statusview_value_for_field(int field) { return this->tss_fields[field]; }; void update_time(void) { status_field &sf = this->tss_fields[TSF_TIME]; time_t current_time = time(NULL); char buffer[32]; strftime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Z", localtime(¤t_time)); sf.set_value(buffer); }; void update_filename(listview_curses *lc) { status_field & sf_partition = this->tss_fields[TSF_PARTITION_NAME]; status_field & sf_format = this->tss_fields[TSF_FORMAT]; status_field & sf_filename = this->tss_fields[TSF_FILENAME]; struct line_range lr(0); if (lc->get_inner_height() > 0) { string_attrs_t::const_iterator line_attr; attr_line_t al; lc->get_data_source()-> listview_value_for_row(*lc, lc->get_top(), al); string_attrs_t &sa = al.get_attrs(); line_attr = find_string_attr(sa, &logline::L_FILE); if (line_attr != sa.end()) { logfile *lf = (logfile *)line_attr->sa_value.sav_ptr; if (lf->get_format()) { sf_format.set_value("% 13s", lf->get_format()->get_name().c_str()); } else if (!lf->get_filename().empty()) { sf_format.set_value("% 13s", "plain text"); } else{ sf_format.clear(); } sf_filename.set_value(lf->get_filename()); } else { sf_format.clear(); sf_filename.clear(); } line_attr = find_string_attr(sa, &logline::L_PARTITION); if (line_attr != sa.end()) { bookmark_metadata *bm = (bookmark_metadata *)line_attr->sa_value.sav_ptr; sf_partition.set_value(bm->bm_name.c_str()); } else { sf_partition.clear(); } } else { sf_format.clear(); sf_filename.set_value(lc->get_data_source()->listview_source_name(*lc)); } sf_format.get_value().get_attrs().push_back( string_attr(lr, &view_curses::VC_STYLE, A_REVERSE | view_colors::ansi_color_pair(COLOR_CYAN, COLOR_BLACK))); }; private: status_field tss_fields[TSF__MAX]; }; #endif lnav-0.7.0/src/view_curses.cc000664 000765 000024 00000032365 12313200604 016364 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file view_curses.cc */ #include "config.h" #include #include #include "lnav_log.hh" #include "view_curses.hh" using namespace std; string_attr_type view_curses::VC_STYLE; string_attr_type view_curses::VC_GRAPHIC; const struct itimerval ui_periodic_timer::INTERVAL = { { 0, 350 * 1000 }, { 0, 350 * 1000 } }; ui_periodic_timer::ui_periodic_timer() { signal(SIGALRM, ui_periodic_timer::sigalrm); if (setitimer(ITIMER_REAL, &INTERVAL, NULL) == -1) { perror("setitimer"); } } ui_periodic_timer &ui_periodic_timer::singleton() { static ui_periodic_timer retval; return retval; } void ui_periodic_timer::sigalrm(int sig) { singleton().upt_counter += 1; } alerter &alerter::singleton() { static alerter retval; return retval; } void view_curses::mvwattrline(WINDOW *window, int y, int x, attr_line_t &al, const struct line_range &lr, view_colors::role_t base_role) { int text_attrs, attrs, line_width; string_attrs_t & sa = al.get_attrs(); string & line = al.get_string(); string_attrs_t::iterator iter; std::map > tab_list; int tab_count = 0; char *expanded_line; size_t exp_index = 0; string full_line; require(lr.lr_end >= 0); line_width = lr.length(); tab_count = count(line.begin(), line.end(), '\t'); expanded_line = (char *)alloca(line.size() + tab_count * 8 + 1); for (size_t lpc = 0; lpc < line.size(); lpc++) { switch (line[lpc]) { case '\t': do { expanded_line[exp_index] = ' '; exp_index += 1; } while (exp_index % 8); tab_list[lpc] = exp_index; break; case '\r': /* exp_index = -1; */ break; case '\n': expanded_line[exp_index] = ' '; exp_index += 1; break; default: expanded_line[exp_index] = line[lpc]; exp_index += 1; break; } } expanded_line[exp_index] = '\0'; full_line = string(expanded_line); text_attrs = view_colors::singleton().attrs_for_role(base_role); attrs = text_attrs; wmove(window, y, x); wattron(window, attrs); if (lr.lr_start < (int)full_line.size()) { waddnstr(window, &full_line.c_str()[lr.lr_start], line_width); } if (lr.lr_end > (int)full_line.size()) { whline(window, ' ', lr.lr_end - full_line.size()); } wattroff(window, attrs); std::vector graphic_range; std::vector graphic_in; stable_sort(sa.begin(), sa.end()); for (iter = sa.begin(); iter != sa.end(); ++iter) { struct line_range attr_range = iter->sa_range; std::map::iterator tab_iter; require(attr_range.lr_start >= 0); require(attr_range.lr_end >= -1); tab_iter = tab_list.lower_bound(attr_range.lr_start); if (tab_iter != tab_list.end()) { if (attr_range.lr_start > tab_iter->first) { attr_range.lr_start += (tab_iter->second - tab_iter->first) - 1; } } if (attr_range.lr_end != -1) { tab_iter = tab_list.lower_bound(attr_range.lr_end); if (tab_iter != tab_list.end()) { if (attr_range.lr_end > tab_iter->first) { attr_range.lr_end += ( tab_iter->second - tab_iter->first) - 1; } } } attr_range.lr_start = max(0, attr_range.lr_start - lr.lr_start); if (attr_range.lr_end == -1) { attr_range.lr_end = lr.lr_start + line_width; } attr_range.lr_end = min((int)line_width, attr_range.lr_end - lr.lr_start); if (attr_range.lr_end > attr_range.lr_start) { string_attrs_t::iterator range_iter; int awidth = attr_range.length(); int color_pair = -1; attrs = 0; for (range_iter = iter; range_iter != sa.end() && range_iter->sa_range == iter->sa_range; ++range_iter) { if (range_iter->sa_type == &VC_STYLE) { if (color_pair <= 0) { color_pair = PAIR_NUMBER(range_iter->sa_value.sav_int); } attrs |= range_iter->sa_value.sav_int; } } if (attrs != 0) { int x_pos = x + attr_range.lr_start; int ch_width = min(awidth, (line_width - attr_range.lr_start)); chtype row_ch[ch_width + 1]; mvwinchnstr(window, y, x_pos, row_ch, ch_width); for (int lpc = 0; lpc < ch_width; lpc++) { if (color_pair > 0) { row_ch[lpc] &= ~A_COLOR; row_ch[lpc] |= (attrs & ~A_COLOR) | COLOR_PAIR(color_pair); } else { row_ch[lpc] |= (attrs); } } mvwaddchnstr(window, y, x_pos, row_ch, ch_width); } for (range_iter = iter; range_iter != sa.end() && range_iter->sa_range == iter->sa_range; ++range_iter) { if (range_iter->sa_type == &VC_GRAPHIC) { graphic_range.push_back(attr_range); graphic_in.push_back(range_iter->sa_value.sav_int | attrs); } } } } for (size_t lpc = 0; lpc < graphic_range.size(); lpc++) { for (int lpc2 = graphic_range[lpc].lr_start; lpc2 < graphic_range[lpc].lr_end; lpc2++) { mvwaddch(window, y, lpc2, graphic_in[lpc]); } } } view_colors &view_colors::singleton(void) { static view_colors s_vc; return s_vc; } view_colors::view_colors() : vc_next_highlight(0), vc_next_plain_highlight(0) { } void view_colors::init(void) { if (has_colors()) { static int ansi_colors_to_curses[] = { COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE, }; start_color(); /* use_default_colors(); */ for (int fg = 0; fg < 8; fg++) { for (int bg = 0; bg < 8; bg++) { if (fg == 0 && bg == 0) continue; init_pair(ansi_color_pair_index(fg, bg), ansi_colors_to_curses[fg], ansi_colors_to_curses[bg]); } } if (COLORS == 256) { int color_pair_base = VC_ANSI_END; for (int z = 0; z < 6; z++) { for (int x = 1; x < 6; x += 2) { for (int y = 1; y < 6; y += 2) { int fg = 16 + x + (y * 6) + (z * 6 * 6); init_pair(color_pair_base, fg, COLOR_BLACK); init_pair(color_pair_base + HL_COLOR_COUNT, COLOR_BLACK, fg); color_pair_base += 1; } } } } } singleton().init_roles(); } void view_colors::init_roles(void) { int lpc; /* Setup the mappings from roles to actual colors. */ this->vc_role_colors[VCR_TEXT] = ansi_color_pair(COLOR_WHITE, COLOR_BLACK) | A_DIM; this->vc_role_colors[VCR_SEARCH] = this->vc_role_colors[VCR_TEXT] | A_REVERSE; this->vc_role_colors[VCR_OK] = ansi_color_pair(COLOR_GREEN, COLOR_BLACK) | A_BOLD; this->vc_role_colors[VCR_ERROR] = ansi_color_pair(COLOR_RED, COLOR_BLACK) | A_BOLD; this->vc_role_colors[VCR_WARNING] = ansi_color_pair(COLOR_YELLOW, COLOR_BLACK) | A_BOLD; this->vc_role_colors[VCR_ALT_ROW] = ansi_color_pair(COLOR_WHITE, COLOR_BLACK) | A_BOLD; this->vc_role_colors[VCR_ADJUSTED_TIME] = ansi_color_pair(COLOR_MAGENTA, COLOR_BLACK); this->vc_role_colors[VCR_STATUS] = ansi_color_pair(COLOR_BLACK, COLOR_WHITE); this->vc_role_colors[VCR_WARN_STATUS] = ansi_color_pair(COLOR_YELLOW, COLOR_WHITE) | A_BOLD; this->vc_role_colors[VCR_ALERT_STATUS] = ansi_color_pair(COLOR_RED, COLOR_WHITE); this->vc_role_colors[VCR_ACTIVE_STATUS] = ansi_color_pair(COLOR_GREEN, COLOR_WHITE); this->vc_role_colors[VCR_ACTIVE_STATUS2] = ansi_color_pair(COLOR_GREEN, COLOR_WHITE) | A_BOLD; this->vc_role_colors[VCR_BOLD_STATUS] = ansi_color_pair(COLOR_BLACK, COLOR_WHITE) | A_BOLD; this->vc_role_colors[VCR_KEYWORD] = ansi_color_pair(COLOR_BLUE, COLOR_BLACK); this->vc_role_colors[VCR_STRING] = ansi_color_pair(COLOR_GREEN, COLOR_BLACK) | A_BOLD; this->vc_role_colors[VCR_COMMENT] = ansi_color_pair(COLOR_GREEN, COLOR_BLACK); this->vc_role_colors[VCR_VARIABLE] = ansi_color_pair(COLOR_CYAN, COLOR_BLACK); this->vc_role_colors[VCR_DIFF_DELETE] = ansi_color_pair(COLOR_RED, COLOR_BLACK); this->vc_role_colors[VCR_DIFF_ADD] = ansi_color_pair(COLOR_GREEN, COLOR_BLACK); this->vc_role_colors[VCR_DIFF_SECTION] = ansi_color_pair(COLOR_MAGENTA, COLOR_BLACK); for (lpc = 0; lpc < VCR_HIGHLIGHT_START; lpc++) { this->vc_role_reverse_colors[lpc] = this->vc_role_colors[lpc] | A_REVERSE; } static int basic_hl_pairs[HL_BASIC_COLOR_COUNT] = { ansi_color_pair(COLOR_BLUE, COLOR_BLACK), ansi_color_pair(COLOR_CYAN, COLOR_BLACK), ansi_color_pair(COLOR_GREEN, COLOR_BLACK), ansi_color_pair(COLOR_MAGENTA, COLOR_BLACK), }; static int basic_rev_hl_pairs[HL_BASIC_COLOR_COUNT] = { ansi_color_pair(COLOR_BLUE, COLOR_WHITE), ansi_color_pair(COLOR_CYAN, COLOR_BLACK), ansi_color_pair(COLOR_GREEN, COLOR_WHITE), ansi_color_pair(COLOR_MAGENTA, COLOR_WHITE), }; for (lpc = 0; lpc < HL_COLOR_COUNT / 2; lpc++) { this->vc_role_colors[VCR_HIGHLIGHT_START + (lpc * 2)] = basic_hl_pairs[ lpc % HL_BASIC_COLOR_COUNT]; this->vc_role_colors[VCR_HIGHLIGHT_START + (lpc * 2) + 1] = basic_hl_pairs[ lpc % HL_BASIC_COLOR_COUNT] | A_BOLD; this->vc_role_reverse_colors[VCR_HIGHLIGHT_START + (lpc * 2)] = basic_rev_hl_pairs[ lpc % HL_BASIC_COLOR_COUNT] | A_REVERSE; this->vc_role_reverse_colors[VCR_HIGHLIGHT_START + (lpc * 2) + 1] = basic_rev_hl_pairs[ lpc % HL_BASIC_COLOR_COUNT] | A_BOLD | A_REVERSE; } if (COLORS >= 256) { int color_pair_base = VC_ANSI_END; /* * Prime the highlight vector. The first HL_COLOR_COUNT color * pairs are assumed to be the highlight colors. */ for (lpc = VCR_HIGHLIGHT_START + HL_BASIC_COLOR_COUNT * 2; lpc < VCR__MAX; lpc++) { this->vc_role_colors[lpc] = COLOR_PAIR(color_pair_base); this->vc_role_reverse_colors[lpc] = COLOR_PAIR(color_pair_base) | A_REVERSE; color_pair_base += 1; } } } view_colors::role_t view_colors::next_highlight() { role_t retval = (role_t)(VCR_HIGHLIGHT_START + this->vc_next_highlight); this->vc_next_highlight = (this->vc_next_highlight + 1) % HL_COLOR_COUNT; return retval; } view_colors::role_t view_colors::next_plain_highlight() { role_t retval = (role_t)(VCR_HIGHLIGHT_START + this->vc_next_plain_highlight); this->vc_next_plain_highlight = (this->vc_next_plain_highlight + 2) % (HL_COLOR_COUNT); return retval; } lnav-0.7.0/src/view_curses.hh000664 000765 000024 00000040472 12313201203 016370 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file view_curses.hh */ #ifndef __view_curses_hh #define __view_curses_hh #include "config.h" #include #include #include #include #include #if defined HAVE_NCURSESW_CURSES_H # include #elif defined HAVE_NCURSESW_H # include #elif defined HAVE_NCURSES_CURSES_H # include #elif defined HAVE_NCURSES_H # include #elif defined HAVE_CURSES_H # include #else # error "SysV or X/Open-compatible Curses header file required" #endif #include #include #include #include #include #include "lnav_log.hh" #define KEY_CTRL_G 7 #define KEY_CTRL_R 18 #define KEY_CTRL_W 23 #define KEY_CTRL_RBRACKET 0x1d class view_curses; /** * An RAII class that initializes and deinitializes curses. */ class screen_curses { public: screen_curses() : sc_main_window(initscr()) { }; virtual ~screen_curses() { endwin(); }; WINDOW *get_window() { return this->sc_main_window; }; private: WINDOW *sc_main_window; }; class ui_periodic_timer { public: static const struct itimerval INTERVAL; static ui_periodic_timer &singleton(); bool time_to_update(sig_atomic_t &counter) const { if (this->upt_counter != counter) { counter = this->upt_counter; return true; } return false; }; private: ui_periodic_timer(); static void sigalrm(int sig); volatile sig_atomic_t upt_counter; }; class alerter { public: static alerter &singleton(); void enabled(bool enable) { this->a_enabled = enable; }; void chime(void) { if (!this->a_enabled) { return; } if (this->a_do_flash) { ::flash(); } this->a_do_flash = false; }; void new_input(int ch) { if (this->a_last_input != ch) { this->a_do_flash = true; } this->a_last_input = ch; }; private: alerter() : a_enabled(false), a_do_flash(true), a_last_input(-1) { }; bool a_enabled; bool a_do_flash; int a_last_input; }; /** * Encapsulates a range in a string. */ struct line_range { int lr_start; int lr_end; line_range(int start = -1, int end = -1) : lr_start(start), lr_end(end) { }; int length() const { return this->lr_end == -1 ? INT_MAX : this->lr_end - this->lr_start; }; bool contains(int pos) const { return this->lr_start <= pos && pos < this->lr_end; }; bool contains(const struct line_range &other) const { return this->contains(other.lr_start) && other.lr_end <= this->lr_end; }; bool intersects(const struct line_range &other) const { return this->contains(other.lr_start) || this->contains(other.lr_end); }; bool operator<(const struct line_range &rhs) const { if (this->lr_start < rhs.lr_start) { return true; } else if (this->lr_start > rhs.lr_start) { return false; } if (this->lr_end == rhs.lr_end) { return false; } if (this->lr_end < rhs.lr_end) { return true; } return false; }; bool operator==(const struct line_range &rhs) const { return (this->lr_start == rhs.lr_start && this->lr_end == rhs.lr_end); }; }; /** * Container for attribute values for a substring. */ typedef union { void *sav_ptr; int sav_int; } string_attr_value_t; class string_attr_type { }; typedef string_attr_type *string_attr_type_t; struct string_attr { string_attr(const struct line_range &lr, string_attr_type_t type, void *val) : sa_range(lr), sa_type(type) { this->sa_value.sav_ptr = val; }; string_attr(const struct line_range &lr, string_attr_type_t type, int val = 0) : sa_range(lr), sa_type(type) { this->sa_value.sav_int = val; }; string_attr() : sa_type(NULL) { }; bool operator<(const struct string_attr &rhs) const { return this->sa_range < rhs.sa_range; }; struct line_range sa_range; string_attr_type_t sa_type; string_attr_value_t sa_value; }; /** A map of line ranges to attributes for that range. */ typedef std::vector string_attrs_t; inline string_attrs_t::const_iterator find_string_attr(const string_attrs_t &sa, string_attr_type_t type) { string_attrs_t::const_iterator iter; struct line_range retval; for (iter = sa.begin(); iter != sa.end(); ++iter) { if (iter->sa_type == type) { break; } } return iter; } inline string_attrs_t::iterator find_string_attr(string_attrs_t &sa, const struct line_range &lr) { string_attrs_t::iterator iter; struct line_range retval; for (iter = sa.begin(); iter != sa.end(); ++iter) { if (lr.contains(iter->sa_range)) { break; } } return iter; } inline struct line_range find_string_attr_range(const string_attrs_t &sa, string_attr_type_t type) { string_attrs_t::const_iterator iter = find_string_attr(sa, type); if (iter != sa.end()) { return iter->sa_range; } return line_range(); } inline void remove_string_attr(string_attrs_t &sa, const struct line_range &lr) { string_attrs_t::iterator iter; while ((iter = find_string_attr(sa, lr)) != sa.end()) { sa.erase(iter); } } /** * A line that has attributes. */ class attr_line_t { public: attr_line_t() { this->al_attrs.reserve(RESERVE_SIZE); }; attr_line_t(const std::string &str) : al_string(str) { this->al_attrs.reserve(RESERVE_SIZE); }; /** @return The string itself. */ std::string &get_string() { return this->al_string; }; /** @return The attributes for the string. */ string_attrs_t &get_attrs() { return this->al_attrs; }; attr_line_t &with_string(const std::string &str) { this->al_string = str; return *this; } attr_line_t &with_attr(const string_attr &sa) { this->al_attrs.push_back(sa); return *this; }; size_t length() const { return this->al_string.length(); }; void operator=(const std::string &rhs) { this->al_string = rhs; }; /** Clear the string and the attributes for the string. */ attr_line_t &clear() { this->al_string.clear(); this->al_attrs.clear(); return *this; }; private: const static size_t RESERVE_SIZE = 128; std::string al_string; string_attrs_t al_attrs; }; /** * Class that encapsulates a method to execute and the object on which to * execute it. * * @param _Sender The type of object that will be triggering an action. */ template class view_action { public: /** * * @param _Receiver The type of object that will be triggered by an action. */ template class mem_functor_t { public: mem_functor_t(_Receiver &receiver, void(_Receiver::*selector)(_Sender *)) : mf_receiver(receiver), mf_selector(selector) { }; void operator()(_Sender *sender) const { (this->mf_receiver.*mf_selector)(sender); }; static void invoke(mem_functor_t *self, _Sender *sender) { (*self)(sender); }; private: _Receiver & mf_receiver; void (_Receiver::*mf_selector)(_Sender *); }; class broadcaster : public std::vector { public: broadcaster() : b_functor(*this, &broadcaster::invoke) { }; virtual ~broadcaster() { }; void invoke(_Sender *sender) { typename std::vector::iterator iter; for (iter = this->begin(); iter != this->end(); ++iter) { (*iter).invoke(sender); } }; mem_functor_t *get_functor() { return &this->b_functor; }; private: mem_functor_t b_functor; }; /** * @param receiver The object to pass as the first argument to the selector * function. * @param selector The function to execute. The function should take two * parameters, the first being the value of the receiver pointer and the * second being the sender pointer as passed to invoke(). */ view_action(void(*invoker)(void *, _Sender *) = NULL) : va_functor(NULL), va_invoker(invoker) { }; template view_action(mem_functor_t<_Receiver> *mf) : va_functor(mf), va_invoker((void(*) (void *, _Sender *)) mem_functor_t<_Receiver>::invoke) { }; /** * Performs a shallow copy of another view_action. * * @param va The view_action to copy the receiver and selector pointers * from. */ view_action(const view_action &va) : va_functor(va.va_functor), va_invoker(va.va_invoker) { }; ~view_action() { }; /** * @param rhs The view_action to shallow copy. * @return *this */ view_action &operator=(const view_action &rhs) { this->va_functor = rhs.va_functor; this->va_invoker = rhs.va_invoker; return *this; }; /** * Invoke the action by calling the selector function, if one is set. * * @param sender Pointer to the object that called this method. */ void invoke(_Sender *sender) { if (this->va_invoker != NULL) { this->va_invoker(this->va_functor, sender); } }; private: /** The object to pass as the first argument to the selector function.*/ void *va_functor; /** The function to call when this action is invoke()'d. */ void (*va_invoker)(void *functor, _Sender *sender); }; /** * Singleton used to manage the colorspace. */ class view_colors { public: /** The number of colors used for highlighting. */ static const int HL_BASIC_COLOR_COUNT = 4; static const int HL_COLOR_COUNT = 2 * HL_BASIC_COLOR_COUNT + 9 * 6; /** Roles that can be mapped to curses attributes using attrs_for_role() */ typedef enum { VCR_NONE = -1, VCR_TEXT, /*< Raw text. */ VCR_SEARCH, /*< A search hit. */ VCR_OK, VCR_ERROR, /*< An error message. */ VCR_WARNING, /*< A warning message. */ VCR_ALT_ROW, /*< Highlight for alternating rows in a list */ VCR_ADJUSTED_TIME, VCR_STATUS, /*< Normal status line text. */ VCR_WARN_STATUS, VCR_ALERT_STATUS, /*< Alert status line text. */ VCR_ACTIVE_STATUS, /*< */ VCR_ACTIVE_STATUS2, /*< */ VCR_BOLD_STATUS, VCR_KEYWORD, VCR_STRING, VCR_COMMENT, VCR_VARIABLE, VCR_DIFF_DELETE, /*< Deleted line in a diff. */ VCR_DIFF_ADD, /*< Added line in a diff. */ VCR_DIFF_SECTION, /*< Section marker in a diff. */ VCR_HIGHLIGHT_START, VCR_HIGHLIGHT_END = VCR_HIGHLIGHT_START + HL_COLOR_COUNT, VCR__MAX } role_t; /** @return A reference to the singleton. */ static view_colors &singleton(); /** * Performs curses-specific initialization. The other methods can be * called before this method, but the returned attributes cannot be used * with curses code until this method is called. */ static void init(void); void init_roles(void); /** * @param role The role to retrieve character attributes for. * @return The attributes to use for the given role. */ int attrs_for_role(role_t role) const { require(role >= 0); require(role < VCR__MAX); return this->vc_role_colors[role]; }; int reverse_attrs_for_role(role_t role) const { require(role >= 0); require(role < VCR__MAX); return this->vc_role_reverse_colors[role]; }; /** * @return The next set of attributes to use for highlighting text. This * method will iterate through eight-or-so attributes combinations so there * is some variety in how text is highlighted. */ role_t next_highlight(); role_t next_plain_highlight(); int attrs_for_ident(const char *str, size_t len) const { int index = crc32(1, (const Bytef*)str, len); int retval; if (COLORS >= 256) { retval = this->vc_role_colors[ VCR_HIGHLIGHT_START + HL_BASIC_COLOR_COUNT * 2 + (abs(index) % (HL_COLOR_COUNT - HL_BASIC_COLOR_COUNT * 2))]; } else { retval = this->vc_role_colors[ VCR_HIGHLIGHT_START + (abs(index) % HL_COLOR_COUNT)]; } return retval; }; int attrs_for_ident(const std::string &str) const { return this->attrs_for_ident(str.c_str(), str.length()); }; static inline int ansi_color_pair_index(int fg, int bg) { return VC_ANSI_START + ((fg * 8) + bg); }; static inline int ansi_color_pair(int fg, int bg) { return COLOR_PAIR(ansi_color_pair_index(fg, bg)); }; enum { VC_ANSI_START = 0, VC_ANSI_END = VC_ANSI_START + (8 * 8), }; private: /** Private constructor that initializes the member fields. */ view_colors(); /** Map of role IDs to attribute values. */ int vc_role_colors[VCR__MAX]; /** Map of role IDs to reverse-video attribute values. */ int vc_role_reverse_colors[VCR__MAX]; /** The index of the next highlight color to use. */ int vc_next_highlight; int vc_next_plain_highlight; }; enum mouse_button_t { BUTTON_LEFT, BUTTON_MIDDLE, BUTTON_RIGHT, BUTTON_SCROLL_UP, BUTTON_SCROLL_DOWN, }; enum mouse_button_state_t { BUTTON_STATE_PRESSED, BUTTON_STATE_DRAGGED, BUTTON_STATE_RELEASED, }; struct mouse_event { mouse_event(mouse_button_t button = BUTTON_LEFT, mouse_button_state_t state = BUTTON_STATE_PRESSED, int x = -1, int y = -1) : me_button(button), me_state(state), me_x(x), me_y(y) { }; mouse_button_t me_button; mouse_button_state_t me_state; struct timeval me_time; int me_x; int me_y; }; /** * Interface for "view" classes that will update a curses(3) display. */ class view_curses { public: virtual ~view_curses() { }; /** * Update the curses display. */ virtual void do_update(void) = 0; virtual bool handle_mouse(mouse_event &me) { return false; }; static string_attr_type VC_STYLE; static string_attr_type VC_GRAPHIC; static void mvwattrline(WINDOW *window, int y, int x, attr_line_t &al, const struct line_range &lr, view_colors::role_t base_role = view_colors::VCR_TEXT); }; #endif lnav-0.7.0/src/vt52_curses.cc000664 000765 000024 00000021242 12306073716 016220 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file vt52_curses.cc */ #include "config.h" #include #include #include #include "lnav_log.hh" #include "vt52_curses.hh" #if defined HAVE_NCURSESW_CURSES_H # include # include #elif defined HAVE_NCURSESW_H # include # include #elif defined HAVE_NCURSES_CURSES_H # include # include #elif defined HAVE_NCURSES_H # include # include #elif defined HAVE_CURSES_H # include # include #else # error "SysV or X/Open-compatible Curses header file required" #endif using namespace std; /** * Singleton used to hold the mapping of ncurses keycodes to VT52 escape * sequences. */ class vt52_escape_map { public: /** @return The singleton. */ static vt52_escape_map &singleton() { static vt52_escape_map s_vem; return s_vem; }; /** * @param ch The ncurses keycode. * @return The null terminated VT52 escape sequence. */ const char *operator[](int ch) const { map::const_iterator iter; const char *retval = NULL; if ((iter = this->vem_map.find(ch)) != this->vem_map.end()) { retval = iter->second; } return retval; }; const char *operator[](const char *seq) const { map::const_iterator iter; const char *retval = NULL; require(seq != NULL); if ((iter = this->vem_input_map.find(seq)) != this->vem_input_map.end()) { retval = iter->second; } return retval; }; private: /** Construct the map with a few escape sequences. */ vt52_escape_map() { static char area_buffer[1024]; char * area = area_buffer; if (tgetent(NULL, "vt52") == ERR) { perror("tgetent"); } this->vem_map[KEY_UP] = tgetstr((char *)"ku", &area); this->vem_map[KEY_DOWN] = tgetstr((char *)"kd", &area); this->vem_map[KEY_RIGHT] = tgetstr((char *)"kr", &area); this->vem_map[KEY_LEFT] = tgetstr((char *)"kl", &area); this->vem_map[KEY_HOME] = tgetstr((char *)"kh", &area); this->vem_map[KEY_BACKSPACE] = "\010"; this->vem_map[KEY_DC] = "\x4"; this->vem_map[KEY_BEG] = "\x1"; this->vem_map[KEY_END] = "\x5"; this->vem_map[KEY_SLEFT] = tgetstr((char *)"#4", &area); if (this->vem_map[KEY_SLEFT] == NULL) { this->vem_map[KEY_SLEFT] = "\033b"; } this->vem_map[KEY_SRIGHT] = tgetstr((char *)"%i", &area); if (this->vem_map[KEY_SRIGHT] == NULL) { this->vem_map[KEY_SRIGHT] = "\033f"; } this->vem_input_map[tgetstr((char *)"ce", &area)] = "ce"; this->vem_input_map[tgetstr((char *)"kl", &area)] = "kl"; this->vem_input_map[tgetstr((char *)"kr", &area)] = "kr"; tgetent(NULL, getenv("TERM")); }; /** Map of ncurses keycodes to VT52 escape sequences. */ map vem_map; map vem_input_map; }; vt52_curses::vt52_curses() : vc_window(NULL), vc_x(0), vc_y(0), vc_max_height(0), vc_escape_len(0), vc_map_buffer(0) { } vt52_curses::~vt52_curses() { } const char *vt52_curses::map_input(int ch, int &len_out) { const char *esc, *retval; /* Check for an escape sequence, otherwise just return the char. */ if ((esc = vt52_escape_map::singleton()[ch]) != NULL) { retval = esc; len_out = strlen(retval); } else { this->vc_map_buffer = (char)ch; retval = &this->vc_map_buffer; /* XXX probably shouldn't do this. */ len_out = 1; } ensure(retval != NULL); ensure(len_out > 0); return retval; } void vt52_curses::map_output(const char *output, int len) { int y, lpc; require(this->vc_window != NULL); y = this->get_actual_y(); wmove(this->vc_window, y, this->vc_x); for (lpc = 0; lpc < len; lpc++) { if (this->vc_escape_len > 0) { const char *cap; this->vc_escape[this->vc_escape_len] = output[lpc]; this->vc_escape_len += 1; this->vc_escape[this->vc_escape_len] = '\0'; if ((cap = vt52_escape_map::singleton()[this->vc_escape]) != NULL) { if (strcmp(cap, "ce") == 0) { wclrtoeol(this->vc_window); this->vc_escape_len = 0; } else if (strcmp(cap, "kl") == 0) { this->vc_x -= 1; wmove(this->vc_window, y, this->vc_x); this->vc_escape_len = 0; } else if (strcmp(cap, "kr") == 0) { this->vc_x += 1; wmove(this->vc_window, y, this->vc_x); this->vc_escape_len = 0; } else { ensure(0); } } } else { switch (output[lpc]) { case STX: this->vc_past_lines.clear(); this->vc_x = 0; wmove(this->vc_window, y, this->vc_x); wclrtoeol(this->vc_window); break; case BELL: flash(); break; case BACKSPACE: this->vc_x -= 1; wmove(this->vc_window, y, this->vc_x); break; case ESCAPE: this->vc_escape[0] = ESCAPE; this->vc_escape_len = 1; break; case '\n': { unsigned long width, height; char * buffer; getmaxyx(this->vc_window, height, width); buffer = (char *)alloca(width); this->vc_x = 0; wmove(this->vc_window, y, this->vc_x); /* * XXX Not sure why we need to subtract one from the width * here, but otherwise it seems to spill over and screw up * the next line when we're writing it back out in * do_update(). */ winnstr(this->vc_window, buffer, width - 1); this->vc_past_lines.push_back(buffer); wclrtoeol(this->vc_window); } break; case '\r': this->vc_x = 0; wmove(this->vc_window, y, this->vc_x); break; default: mvwaddch(this->vc_window, y, this->vc_x, output[lpc]); this->vc_x += 1; break; } } } } void vt52_curses::do_update(void) { list::iterator iter; int y; y = this->get_actual_y() - (int)this->vc_past_lines.size(); for (iter = this->vc_past_lines.begin(); iter != this->vc_past_lines.end(); ++iter, y++) { if (y >= 0) { mvwprintw(this->vc_window, y, 0, "%s", iter->c_str()); wclrtoeol(this->vc_window); } } wmove(this->vc_window, y, this->vc_x); } lnav-0.7.0/src/vt52_curses.hh000664 000765 000024 00000013602 12211635054 016225 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file vt52_curses.hh */ #ifndef __vt52_curses_hh #define __vt52_curses_hh #include #include #include "view_curses.hh" /** * VT52 emulator for curses, useful for mediating between curses and readline, * which don't play well together. It is expected that a subclass of this * class will fork off a child process that sends and receives VT52 keycodes(?) * which is translated by this class into curses calls. * * VT52 seems to be the simplest terminal to emulate since we do not need to * maintain the state of the screen, beyond past lines. For example, when * inserting a character, VT52 moves the cursor to the insertion point, clears * the rest of the line and then rewrites the rest of the line with the new * character. This is in contrast to VT100 which moves the cursor to the * insertion point and then sends a code to insert the character and relying * on the terminal to shift the rest of the line to the right a character. */ class vt52_curses : public view_curses { public: vt52_curses(); virtual ~vt52_curses(); /** @param win The curses window this view is attached to. */ void set_window(WINDOW *win) { this->vc_window = win; }; /** @return The curses window this view is attached to. */ WINDOW *get_window() { return this->vc_window; }; /** * Set the Y position of this view on the display. A value greater than * zero is considered to be an absolute size. A value less than zero makes * the position relative to the bottom of the enclosing window. * * @param y The Y position of the cursor on the curses display. */ void set_y(int y) { this->vc_y = y; }; /** @return The abs/rel Y position of the cursor on the curses display. */ int get_y() const { return this->vc_y; }; /** @param x The X position of the cursor on the curses display. */ void set_x(int x) { this->vc_x = x; }; /** @return The X position of the cursor on the curses display. */ int get_x() const { return this->vc_x; }; /** * @return The height of this view, which consists of a single line for * input, plus any past lines of output, which will appear ABOVE the Y * position for this view. * @todo Kinda hardwired to the way readline works. */ int get_height() { return this->vc_past_lines.size() + 1; }; void set_max_height(int mh) { this->vc_max_height = mh; }; int get_max_height() const { return this->vc_max_height; }; /** * Map an ncurses input keycode to a vt52 sequence. * * @param ch The input character. * @param len_out The length of the returned sequence. * @return The vt52 sequence to send to the child. */ const char *map_input(int ch, int &len_out); /** * Map VT52 output to ncurses calls. * * @param output VT52 encoded output from the child process. * @param len The length of the output array. */ void map_output(const char *output, int len); /** * Paints any past lines and moves the cursor to the current X position. */ void do_update(void); const static char ESCAPE = 27; /*< VT52 Escape key value. */ const static char BACKSPACE = 8; /*< VT52 Backspace key value. */ const static char BELL = 7; /*< VT52 Bell value. */ const static char STX = 2; /*< VT52 Start-of-text value. */ protected: /** @return The absolute Y position of this view. */ int get_actual_y() { unsigned long width, height; int retval; getmaxyx(this->vc_window, height, width); if (this->vc_y < 0) { retval = height + this->vc_y; } else { retval = this->vc_y; } return retval; }; WINDOW *vc_window; /*< The window that contains this view. */ int vc_x; /*< The X position of the cursor. */ int vc_y; /*< The Y position of the cursor. */ int vc_max_height; char vc_escape[16]; /*< Storage for escape sequences. */ int vc_escape_len; /*< The number of chars in vc_escape. */ char vc_map_buffer; /*< * Buffer returned by map_input for trivial * translations (one-to-one). */ /** Vector of past lines of output from the child. */ std::list vc_past_lines; }; #endif lnav-0.7.0/src/xterm_mouse.cc000664 000765 000024 00000003450 12216211402 016366 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "xterm_mouse.hh" const char *xterm_mouse::XT_TERMCAP = "\033[?1000%?%p1%{1}%=%th%el%;"; const char *xterm_mouse::XT_TERMCAP_TRACKING = "\033[?1002%?%p1%{1}%=%th%el%;"; const char *xterm_mouse::XT_TERMCAP_SGR = "\033[?1006%?%p1%{1}%=%th%el%;"; lnav-0.7.0/src/xterm_mouse.hh000664 000765 000024 00000013412 12305040051 016376 0ustar00stackstaff000000 000000 /** * Copyright (c) 2007-2012, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file xterm_mouse.hh */ #ifndef __xterm_mouse_hh #define __xterm_mouse_hh #include #include #include #include #if defined HAVE_NCURSESW_CURSES_H # include #elif defined HAVE_NCURSESW_H # include #elif defined HAVE_NCURSES_CURSES_H # include #elif defined HAVE_NCURSES_H # include #elif defined HAVE_CURSES_H # include #else # error "SysV or X/Open-compatible Curses header file required" #endif #include "lnav_log.hh" /** * Base class for delegates of the xterm_mouse class. */ class mouse_behavior { public: virtual ~mouse_behavior() { }; /** * Callback used to process mouse events. * * @param button The button that was pressed or released. This will * be one of the XT_BUTTON or XT_SCROLL constants in the xterm_mouse * class. * @param x The X coordinate where the event occurred. * @param y The Y coordinate where the event occurred. */ virtual void mouse_event(int button, bool release, int x, int y) = 0; }; /** * Class that handles xterm mouse events coming through the ncurses interface. */ class xterm_mouse { public: static const int XT_BUTTON1 = 0; static const int XT_BUTTON2 = 1; static const int XT_BUTTON3 = 2; static const int XT_DRAG_FLAG = 32; static const int XT_SCROLL_WHEEL_FLAG = 64; static const int XT_SCROLL_UP = XT_SCROLL_WHEEL_FLAG | XT_BUTTON1; static const int XT_SCROLL_DOWN = XT_SCROLL_WHEEL_FLAG | XT_BUTTON2; static const int XT_BUTTON__MASK = XT_SCROLL_WHEEL_FLAG | XT_BUTTON1 | XT_BUTTON2 | XT_BUTTON3; static const char *XT_TERMCAP; static const char *XT_TERMCAP_TRACKING; static const char *XT_TERMCAP_SGR; /** * @return True if the user's terminal supports xterm-mouse events. */ static bool is_available() { const char *termname = getenv("TERM"); bool retval = false; if (termname and strstr(termname, "xterm") != NULL) { retval = isatty(STDOUT_FILENO); } return retval; }; xterm_mouse() : xm_enabled(false), xm_behavior(NULL) {}; ~xterm_mouse() { if (this->is_enabled()) set_enabled(false); }; /** * @param enabled True if xterm mouse support should be enabled in the * terminal. */ void set_enabled(bool enabled) { if (is_available()) { putp(tparm((char *)XT_TERMCAP, enabled ? 1 : 0)); putp(tparm((char *)XT_TERMCAP_TRACKING, enabled ? 1 : 0)); putp(tparm((char *)XT_TERMCAP_SGR, enabled ? 1 : 0)); this->xm_enabled = enabled; } }; /** * @return True if xterm mouse support is enabled, false otherwise. */ bool is_enabled() const { return this->xm_enabled; }; /** * @param mb The delegate to send mouse events to. */ void set_behavior(mouse_behavior *mb) { this->xm_behavior = mb; }; mouse_behavior *get_behavior() { return this->xm_behavior; }; /** * Handle a KEY_MOUSE character from ncurses. * @param ch unused */ void handle_mouse(int ch_unused) { bool release = false; int ch; size_t index = 0; int bstate, x, y; char buffer[64]; bool done = false; while (!done) { if (index >= sizeof(buffer) - 1) { break; } ch = getch(); switch (ch) { case 'm': release = true; done = true; break; case 'M': done = true; break; default: buffer[index++] = (char)ch; break; } } buffer[index] = '\0'; if (sscanf(buffer, "<%d;%d;%d", &bstate, &x, &y) == 3) { if (this->xm_behavior) { this->xm_behavior->mouse_event(bstate, release, x, y); } } else { log_error("bad mouse escape sequence: %s", buffer); } }; private: bool xm_enabled; mouse_behavior *xm_behavior; }; #endif lnav-0.7.0/src/yajl/000775 000765 000024 00000000000 12315725122 014456 5ustar00stackstaff000000 000000 lnav-0.7.0/src/yajlpp.cc000664 000765 000024 00000016536 12215056710 015337 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file yajlpp.cc */ #include "config.h" #include "yajlpp.hh" int yajlpp_parse_context::map_start(void *ctx) { yajlpp_parse_context *ypc = (yajlpp_parse_context *)ctx; int retval = 1; ypc->ypc_path_index_stack.push_back(ypc->ypc_path.size() - 1); if (ypc->ypc_path.size() > 1 && ypc->ypc_path[ypc->ypc_path.size() - 2] == '#') { ypc->ypc_array_index.back() += 1; } if (ypc->ypc_alt_callbacks.yajl_start_map != NULL) retval = ypc->ypc_alt_callbacks.yajl_start_map(ypc); return retval; } int yajlpp_parse_context::map_key(void *ctx, const unsigned char *key, size_t len) { yajlpp_parse_context *ypc = (yajlpp_parse_context *)ctx; int start, retval = 1; ypc->ypc_path.resize(ypc->ypc_path_index_stack.back()); ypc->ypc_path.push_back('/'); start = ypc->ypc_path.size(); ypc->ypc_path.resize(ypc->ypc_path.size() + len); memcpy(&ypc->ypc_path[start], key, len); ypc->ypc_path.push_back('\0'); if (ypc->ypc_alt_callbacks.yajl_map_key != NULL) retval = ypc->ypc_alt_callbacks.yajl_map_key(ctx, key, len); ypc->update_callbacks(); return retval; } void yajlpp_parse_context::update_callbacks(void) { pcre_input pi(&this->ypc_path[0], 0, this->ypc_path.size() - 1); this->ypc_callbacks = DEFAULT_CALLBACKS; for (int lpc = 0; this->ypc_handlers[lpc].jph_path[0]; lpc++) { const json_path_handler &jph = this->ypc_handlers[lpc]; pi.reset(&this->ypc_path[0], 0, this->ypc_path.size() - 1); if (jph.jph_regex.match(this->ypc_pcre_context, pi)) { if (jph.jph_callbacks.yajl_null != NULL) this->ypc_callbacks.yajl_null = jph.jph_callbacks.yajl_null; if (jph.jph_callbacks.yajl_boolean != NULL) this->ypc_callbacks.yajl_boolean = jph.jph_callbacks.yajl_boolean; if (jph.jph_callbacks.yajl_integer != NULL) this->ypc_callbacks.yajl_integer = jph.jph_callbacks.yajl_integer; if (jph.jph_callbacks.yajl_double != NULL) this->ypc_callbacks.yajl_double = jph.jph_callbacks.yajl_double; if (jph.jph_callbacks.yajl_string != NULL) this->ypc_callbacks.yajl_string = jph.jph_callbacks.yajl_string; } } } int yajlpp_parse_context::map_end(void *ctx) { yajlpp_parse_context *ypc = (yajlpp_parse_context *)ctx; int retval = 1; ypc->ypc_path.resize(ypc->ypc_path_index_stack.back()); ypc->ypc_path.push_back('\0'); ypc->ypc_path_index_stack.pop_back(); if (ypc->ypc_alt_callbacks.yajl_end_map != NULL) retval = ypc->ypc_alt_callbacks.yajl_end_map(ctx); ypc->update_callbacks(); return retval; } int yajlpp_parse_context::array_start(void *ctx) { yajlpp_parse_context *ypc = (yajlpp_parse_context *)ctx; int retval = 1; ypc->ypc_path_index_stack.push_back(ypc->ypc_path.size() - 1); ypc->ypc_path[ypc->ypc_path.size() - 1] = '#'; ypc->ypc_path.push_back('\0'); ypc->ypc_array_index.push_back(-1); if (ypc->ypc_alt_callbacks.yajl_start_array != NULL) retval = ypc->ypc_alt_callbacks.yajl_start_array(ctx); ypc->update_callbacks(); return retval; } int yajlpp_parse_context::array_end(void *ctx) { yajlpp_parse_context *ypc = (yajlpp_parse_context *)ctx; int retval = 1; ypc->ypc_path.resize(ypc->ypc_path_index_stack.back()); ypc->ypc_path.push_back('\0'); ypc->ypc_path_index_stack.pop_back(); ypc->ypc_array_index.pop_back(); if (ypc->ypc_alt_callbacks.yajl_end_array != NULL) retval = ypc->ypc_alt_callbacks.yajl_end_array(ctx); ypc->update_callbacks(); return retval; } int yajlpp_parse_context::handle_unused(void *ctx) { yajlpp_parse_context *ypc = (yajlpp_parse_context *)ctx; if (ypc->ypc_ignore_unused) return 1; fprintf(stderr, "warning:%s:%s:unexpected data, expecting one of the following data types --\n", ypc->ypc_source.c_str(), &ypc->ypc_path[0]); if (ypc->ypc_callbacks.yajl_boolean != (int (*)(void *, int))yajlpp_parse_context::handle_unused) { fprintf(stderr, "warning:%s:%s: boolean\n", ypc->ypc_source.c_str(), &ypc->ypc_path[0]); } if (ypc->ypc_callbacks.yajl_integer != (int (*)(void *, long long))yajlpp_parse_context::handle_unused) { fprintf(stderr, "warning:%s:%s: integer\n", ypc->ypc_source.c_str(), &ypc->ypc_path[0]); } if (ypc->ypc_callbacks.yajl_double != (int (*)(void *, double))yajlpp_parse_context::handle_unused) { fprintf(stderr, "warning:%s:%s: float\n", ypc->ypc_source.c_str(), &ypc->ypc_path[0]); } if (ypc->ypc_callbacks.yajl_string != (int (*)(void *, const unsigned char *, size_t))yajlpp_parse_context::handle_unused) { fprintf(stderr, "warning:%s:%s: string\n", ypc->ypc_source.c_str(), &ypc->ypc_path[0]); } fprintf(stderr, "warning:%s:%s:accepted paths --\n", ypc->ypc_source.c_str(), &ypc->ypc_path[0]); for (int lpc = 0; ypc->ypc_handlers[lpc].jph_path[0]; lpc++) { fprintf(stderr, "warning:%s:%s: %s\n", ypc->ypc_source.c_str(), &ypc->ypc_path[0], ypc->ypc_handlers[lpc].jph_path); } return 1; } const yajl_callbacks yajlpp_parse_context::DEFAULT_CALLBACKS = { yajlpp_parse_context::handle_unused, (int (*)(void *, int))yajlpp_parse_context::handle_unused, (int (*)(void *, long long))yajlpp_parse_context::handle_unused, (int (*)(void *, double))yajlpp_parse_context::handle_unused, NULL, (int (*)(void *, const unsigned char *, size_t)) yajlpp_parse_context::handle_unused, yajlpp_parse_context::map_start, yajlpp_parse_context::map_key, yajlpp_parse_context::map_end, yajlpp_parse_context::array_start, yajlpp_parse_context::array_end, }; lnav-0.7.0/src/yajlpp.hh000664 000765 000024 00000021245 12307601632 015343 0ustar00stackstaff000000 000000 /** * Copyright (c) 2013, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @file yajlpp.hh */ #ifndef _yajlpp_hh #define _yajlpp_hh #include #include #include #include #include "pcrepp.hh" #include "yajl/api/yajl_parse.h" #include "yajl/api/yajl_gen.h" inline yajl_gen_status yajl_gen_pstring(yajl_gen hand, const char *str, size_t len) { if (len == (size_t)-1) { len = strlen(str); } return yajl_gen_string(hand, (const unsigned char *)str, len); } inline yajl_gen_status yajl_gen_string(yajl_gen hand, const std::string &str) { return yajl_gen_string(hand, (const unsigned char *)str.c_str(), str.length()); } struct json_path_handler_base { json_path_handler_base(const char *path) : jph_path(path), jph_regex(path) { memset(&this->jph_callbacks, 0, sizeof(this->jph_callbacks)); }; const char * jph_path; pcrepp jph_regex; yajl_callbacks jph_callbacks; }; class yajlpp_parse_context; struct json_path_handler : public json_path_handler_base { json_path_handler(const char *path, int(*null_func)(yajlpp_parse_context *)) : json_path_handler_base(path) { this->jph_callbacks.yajl_null = (int (*)(void *))null_func; }; json_path_handler(const char *path, int(*bool_func)(yajlpp_parse_context *, int)) : json_path_handler_base(path) { this->jph_callbacks.yajl_boolean = (int (*)(void *, int))bool_func; } json_path_handler(const char *path, int(*int_func)(yajlpp_parse_context *, long long)) : json_path_handler_base(path) { this->jph_callbacks.yajl_integer = (int (*)(void *, long long))int_func; } json_path_handler(const char *path, int(*double_func)(yajlpp_parse_context *, double)) : json_path_handler_base(path) { this->jph_callbacks.yajl_double = (int (*)(void *, double))double_func; } json_path_handler(const char *path, int(*str_func)(yajlpp_parse_context *, const unsigned char *, size_t)) : json_path_handler_base(path) { this->jph_callbacks.yajl_string = (int (*)(void *, const unsigned char *, size_t))str_func; } json_path_handler(const char *path) : json_path_handler_base(path) { }; json_path_handler() : json_path_handler_base("") {}; json_path_handler &add_cb(int(*null_func)(yajlpp_parse_context *)) { this->jph_callbacks.yajl_null = (int (*)(void *))null_func; return *this; }; json_path_handler &add_cb(int(*bool_func)(yajlpp_parse_context *, int)) { this->jph_callbacks.yajl_boolean = (int (*)(void *, int))bool_func; return *this; } json_path_handler &add_cb(int(*int_func)(yajlpp_parse_context *, long long)) { this->jph_callbacks.yajl_integer = (int (*)(void *, long long))int_func; return *this; } json_path_handler &add_cb(int(*double_func)(yajlpp_parse_context *, double)) { this->jph_callbacks.yajl_double = (int (*)(void *, double))double_func; return *this; } json_path_handler &add_cb(int(*str_func)(yajlpp_parse_context *, const unsigned char *, size_t)) { this->jph_callbacks.yajl_string = (int (*)(void *, const unsigned char *, size_t))str_func; return *this; } }; class yajlpp_parse_context { public: struct json_path_element { json_path_element(int index = 0) : jpe_index(index) { }; json_path_element(const std::string &name) : jpe_name(name), jpe_index(0) {}; json_path_element(const unsigned char *name) : jpe_name((const char *)name), jpe_index(0) {}; void set_name(const unsigned char *name, size_t len) { this->jpe_name = std::string((const char *)name, len); }; std::string jpe_name; int jpe_index; }; yajlpp_parse_context(std::string source, struct json_path_handler *handlers = NULL) : ypc_source(source), ypc_handlers(handlers), ypc_ignore_unused(false) { this->ypc_path.reserve(4096); this->ypc_path.push_back('\0'); this->ypc_callbacks = DEFAULT_CALLBACKS; memset(&this->ypc_alt_callbacks, 0, sizeof(this->ypc_alt_callbacks)); }; std::string get_path_fragment(int offset) const { size_t start, end; if (offset < 0) { offset = this->ypc_path_index_stack.size() + offset; } start = this->ypc_path_index_stack[offset] + 1; if ((offset + 1) < (int)this->ypc_path_index_stack.size()) { end = this->ypc_path_index_stack[offset + 1]; } else{ end = this->ypc_path.size() - 1; } return std::string(&this->ypc_path[start], end - start); }; void reset(struct json_path_handler *handlers) { this->ypc_handlers = handlers; this->ypc_path.clear(); this->ypc_path.push_back('\0'); this->ypc_path_index_stack.clear(); this->ypc_array_index.clear(); this->ypc_callbacks = DEFAULT_CALLBACKS; memset(&this->ypc_alt_callbacks, 0, sizeof(this->ypc_alt_callbacks)); } const std::string ypc_source; struct json_path_handler *ypc_handlers; void * ypc_userdata; yajl_callbacks ypc_callbacks; yajl_callbacks ypc_alt_callbacks; std::vector ypc_path; std::vector ypc_path_index_stack; std::vector ypc_array_index; pcre_context_static<30> ypc_pcre_context; bool ypc_ignore_unused; private: static const yajl_callbacks DEFAULT_CALLBACKS; void update_callbacks(void); static int map_start(void *ctx); static int map_key(void *ctx, const unsigned char *key, size_t len); static int map_end(void *ctx); static int array_start(void *ctx); static int array_end(void *ctx); static int handle_unused(void *ctx); }; class yajlpp_generator { public: yajlpp_generator(yajl_gen handle) : yg_handle(handle) { }; void operator()(const std::string &str) { yajl_gen_string(this->yg_handle, str); }; void operator()(const char *str) { yajl_gen_string(this->yg_handle, (const unsigned char *)str, strlen(str)); }; void operator()(long long value) { yajl_gen_integer(this->yg_handle, value); }; void operator()(bool value) { yajl_gen_bool(this->yg_handle, value); }; void operator()() { yajl_gen_null(this->yg_handle); }; private: yajl_gen yg_handle; }; class yajlpp_container_base { public: yajlpp_container_base(yajl_gen handle) : gen(handle), ycb_handle(handle) {}; yajlpp_generator gen; protected: yajl_gen ycb_handle; }; class yajlpp_map : public yajlpp_container_base { public: yajlpp_map(yajl_gen handle) : yajlpp_container_base(handle) { yajl_gen_map_open(handle); }; ~yajlpp_map() { yajl_gen_map_close(this->ycb_handle); }; }; class yajlpp_array : public yajlpp_container_base { public: yajlpp_array(yajl_gen handle) : yajlpp_container_base(handle) { yajl_gen_array_open(handle); }; ~yajlpp_array() { yajl_gen_array_close(this->ycb_handle); }; }; #endif lnav-0.7.0/src/yajl/api/000775 000765 000024 00000000000 12315725122 015227 5ustar00stackstaff000000 000000 lnav-0.7.0/src/yajl/yajl.c000664 000765 000024 00000011532 12211635054 015562 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "api/yajl_parse.h" #include "yajl_lex.h" #include "yajl_parser.h" #include "yajl_alloc.h" #include #include #include #include const char * yajl_status_to_string(yajl_status stat) { const char * statStr = "unknown"; switch (stat) { case yajl_status_ok: statStr = "ok, no error"; break; case yajl_status_client_canceled: statStr = "client canceled parse"; break; case yajl_status_error: statStr = "parse error"; break; } return statStr; } yajl_handle yajl_alloc(const yajl_callbacks * callbacks, yajl_alloc_funcs * afs, void * ctx) { yajl_handle hand = NULL; yajl_alloc_funcs afsBuffer; /* first order of business is to set up memory allocation routines */ if (afs != NULL) { if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL) { return NULL; } } else { yajl_set_default_alloc_funcs(&afsBuffer); afs = &afsBuffer; } hand = (yajl_handle) YA_MALLOC(afs, sizeof(struct yajl_handle_t)); /* copy in pointers to allocation routines */ memcpy((void *) &(hand->alloc), (void *) afs, sizeof(yajl_alloc_funcs)); hand->callbacks = callbacks; hand->ctx = ctx; hand->lexer = NULL; hand->bytesConsumed = 0; hand->decodeBuf = yajl_buf_alloc(&(hand->alloc)); hand->flags = 0; yajl_bs_init(hand->stateStack, &(hand->alloc)); yajl_bs_push(hand->stateStack, yajl_state_start); return hand; } int yajl_config(yajl_handle h, yajl_option opt, ...) { int rv = 1; va_list ap; va_start(ap, opt); switch(opt) { case yajl_allow_comments: case yajl_dont_validate_strings: case yajl_allow_trailing_garbage: case yajl_allow_multiple_values: case yajl_allow_partial_values: if (va_arg(ap, int)) h->flags |= opt; else h->flags &= ~opt; break; default: rv = 0; } va_end(ap); return rv; } void yajl_free(yajl_handle handle) { yajl_bs_free(handle->stateStack); yajl_buf_free(handle->decodeBuf); if (handle->lexer) { yajl_lex_free(handle->lexer); handle->lexer = NULL; } YA_FREE(&(handle->alloc), handle); } yajl_status yajl_parse(yajl_handle hand, const unsigned char * jsonText, size_t jsonTextLen) { yajl_status status; /* lazy allocation of the lexer */ if (hand->lexer == NULL) { hand->lexer = yajl_lex_alloc(&(hand->alloc), hand->flags & yajl_allow_comments, !(hand->flags & yajl_dont_validate_strings)); } status = yajl_do_parse(hand, jsonText, jsonTextLen); return status; } yajl_status yajl_complete_parse(yajl_handle hand) { /* The lexer is lazy allocated in the first call to parse. if parse is * never called, then no data was provided to parse at all. This is a * "premature EOF" error unless yajl_allow_partial_values is specified. * allocating the lexer now is the simplest possible way to handle this * case while preserving all the other semantics of the parser * (multiple values, partial values, etc). */ if (hand->lexer == NULL) { hand->lexer = yajl_lex_alloc(&(hand->alloc), hand->flags & yajl_allow_comments, !(hand->flags & yajl_dont_validate_strings)); } return yajl_do_finish(hand); } unsigned char * yajl_get_error(yajl_handle hand, int verbose, const unsigned char * jsonText, size_t jsonTextLen) { return yajl_render_error_string(hand, jsonText, jsonTextLen, verbose); } size_t yajl_get_bytes_consumed(yajl_handle hand) { if (!hand) return 0; else return hand->bytesConsumed; } void yajl_free_error(yajl_handle hand, unsigned char * str) { /* use memory allocation functions if set */ YA_FREE(&(hand->alloc), str); } /* XXX: add utility routines to parse from file */ lnav-0.7.0/src/yajl/yajl_alloc.c000664 000765 000024 00000002701 12211635054 016732 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * \file yajl_alloc.h * default memory allocation routines for yajl which use malloc/realloc and * free */ #include "yajl_alloc.h" #include static void * yajl_internal_malloc(void *ctx, size_t sz) { return malloc(sz); } static void * yajl_internal_realloc(void *ctx, void * previous, size_t sz) { return realloc(previous, sz); } static void yajl_internal_free(void *ctx, void * ptr) { free(ptr); } void yajl_set_default_alloc_funcs(yajl_alloc_funcs * yaf) { yaf->malloc = yajl_internal_malloc; yaf->free = yajl_internal_free; yaf->realloc = yajl_internal_realloc; yaf->ctx = NULL; } lnav-0.7.0/src/yajl/yajl_alloc.h000664 000765 000024 00000002347 12211635054 016745 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * \file yajl_alloc.h * default memory allocation routines for yajl which use malloc/realloc and * free */ #ifndef __YAJL_ALLOC_H__ #define __YAJL_ALLOC_H__ #include "api/yajl_common.h" #define YA_MALLOC(afs, sz) (afs)->malloc((afs)->ctx, (sz)) #define YA_FREE(afs, ptr) (afs)->free((afs)->ctx, (ptr)) #define YA_REALLOC(afs, ptr, sz) (afs)->realloc((afs)->ctx, (ptr), (sz)) void yajl_set_default_alloc_funcs(yajl_alloc_funcs * yaf); #endif lnav-0.7.0/src/yajl/yajl_buf.c000664 000765 000024 00000004740 12211635054 016421 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "yajl_buf.h" #include #include #include #define YAJL_BUF_INIT_SIZE 2048 struct yajl_buf_t { size_t len; size_t used; unsigned char * data; yajl_alloc_funcs * alloc; }; static void yajl_buf_ensure_available(yajl_buf buf, size_t want) { size_t need; assert(buf != NULL); /* first call */ if (buf->data == NULL) { buf->len = YAJL_BUF_INIT_SIZE; buf->data = (unsigned char *) YA_MALLOC(buf->alloc, buf->len); buf->data[0] = 0; } need = buf->len; while (want >= (need - buf->used)) need <<= 1; if (need != buf->len) { buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need); buf->len = need; } } yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc) { yajl_buf b = YA_MALLOC(alloc, sizeof(struct yajl_buf_t)); memset((void *) b, 0, sizeof(struct yajl_buf_t)); b->alloc = alloc; return b; } void yajl_buf_free(yajl_buf buf) { assert(buf != NULL); if (buf->data) YA_FREE(buf->alloc, buf->data); YA_FREE(buf->alloc, buf); } void yajl_buf_append(yajl_buf buf, const void * data, size_t len) { yajl_buf_ensure_available(buf, len); if (len > 0) { assert(data != NULL); memcpy(buf->data + buf->used, data, len); buf->used += len; buf->data[buf->used] = 0; } } void yajl_buf_clear(yajl_buf buf) { buf->used = 0; if (buf->data) buf->data[buf->used] = 0; } const unsigned char * yajl_buf_data(yajl_buf buf) { return buf->data; } size_t yajl_buf_len(yajl_buf buf) { return buf->used; } void yajl_buf_truncate(yajl_buf buf, size_t len) { assert(len <= buf->used); buf->used = len; } lnav-0.7.0/src/yajl/yajl_buf.h000664 000765 000024 00000003511 12211635054 016421 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __YAJL_BUF_H__ #define __YAJL_BUF_H__ #include "api/yajl_common.h" #include "yajl_alloc.h" /* * Implementation/performance notes. If this were moved to a header * only implementation using #define's where possible we might be * able to sqeeze a little performance out of the guy by killing function * call overhead. YMMV. */ /** * yajl_buf is a buffer with exponential growth. the buffer ensures that * you are always null padded. */ typedef struct yajl_buf_t * yajl_buf; /* allocate a new buffer */ yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc); /* free the buffer */ void yajl_buf_free(yajl_buf buf); /* append a number of bytes to the buffer */ void yajl_buf_append(yajl_buf buf, const void * data, size_t len); /* empty the buffer */ void yajl_buf_clear(yajl_buf buf); /* get a pointer to the beginning of the buffer */ const unsigned char * yajl_buf_data(yajl_buf buf); /* get the length of the buffer */ size_t yajl_buf_len(yajl_buf buf); /* truncate the buffer */ void yajl_buf_truncate(yajl_buf buf, size_t len); #endif lnav-0.7.0/src/yajl/yajl_bytestack.h000664 000765 000024 00000004521 12211635054 017640 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * A header only implementation of a simple stack of bytes, used in YAJL * to maintain parse state. */ #ifndef __YAJL_BYTESTACK_H__ #define __YAJL_BYTESTACK_H__ #include "api/yajl_common.h" #define YAJL_BS_INC 128 typedef struct yajl_bytestack_t { unsigned char * stack; size_t size; size_t used; yajl_alloc_funcs * yaf; } yajl_bytestack; /* initialize a bytestack */ #define yajl_bs_init(obs, _yaf) { \ (obs).stack = NULL; \ (obs).size = 0; \ (obs).used = 0; \ (obs).yaf = (_yaf); \ } \ /* initialize a bytestack */ #define yajl_bs_free(obs) \ if ((obs).stack) (obs).yaf->free((obs).yaf->ctx, (obs).stack); #define yajl_bs_current(obs) \ (assert((obs).used > 0), (obs).stack[(obs).used - 1]) #define yajl_bs_push(obs, byte) { \ if (((obs).size - (obs).used) == 0) { \ (obs).size += YAJL_BS_INC; \ (obs).stack = (obs).yaf->realloc((obs).yaf->ctx,\ (void *) (obs).stack, (obs).size);\ } \ (obs).stack[((obs).used)++] = (byte); \ } /* removes the top item of the stack, returns nothing */ #define yajl_bs_pop(obs) { ((obs).used)--; } #define yajl_bs_set(obs, byte) \ (obs).stack[((obs).used) - 1] = (byte); #endif lnav-0.7.0/src/yajl/yajl_common.h000664 000765 000024 00000005002 12211635054 017132 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __YAJL_COMMON_H__ #define __YAJL_COMMON_H__ #include #ifdef __cplusplus extern "C" { #endif #define YAJL_MAX_DEPTH 128 /* msft dll export gunk. To build a DLL on windows, you * must define WIN32, YAJL_SHARED, and YAJL_BUILD. To use a shared * DLL, you must define YAJL_SHARED and WIN32 */ #if defined(WIN32) && defined(YAJL_SHARED) # ifdef YAJL_BUILD # define YAJL_API __declspec(dllexport) # else # define YAJL_API __declspec(dllimport) # endif #else # if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303 # define YAJL_API __attribute__ ((visibility("default"))) # else # define YAJL_API # endif #endif /** pointer to a malloc function, supporting client overriding memory * allocation routines */ typedef void * (*yajl_malloc_func)(void *ctx, size_t sz); /** pointer to a free function, supporting client overriding memory * allocation routines */ typedef void (*yajl_free_func)(void *ctx, void * ptr); /** pointer to a realloc function which can resize an allocation. */ typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, size_t sz); /** A structure which can be passed to yajl_*_alloc routines to allow the * client to specify memory allocation functions to be used. */ typedef struct { /** pointer to a function that can allocate uninitialized memory */ yajl_malloc_func malloc; /** pointer to a function that can resize memory allocations */ yajl_realloc_func realloc; /** pointer to a function that can free memory allocated using * reallocFunction or mallocFunction */ yajl_free_func free; /** a context pointer that will be passed to above allocation routines */ void * ctx; } yajl_alloc_funcs; #ifdef __cplusplus } #endif #endif lnav-0.7.0/src/yajl/yajl_encode.c000664 000765 000024 00000016156 12211635054 017106 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "yajl_encode.h" #include #include #include #include static void CharToHex(unsigned char c, char * hexBuf) { const char * hexchar = "0123456789ABCDEF"; hexBuf[0] = hexchar[c >> 4]; hexBuf[1] = hexchar[c & 0x0F]; } void yajl_string_encode(const yajl_print_t print, void * ctx, const unsigned char * str, size_t len, int escape_solidus) { size_t beg = 0; size_t end = 0; char hexBuf[7]; hexBuf[0] = '\\'; hexBuf[1] = 'u'; hexBuf[2] = '0'; hexBuf[3] = '0'; hexBuf[6] = 0; while (end < len) { const char * escaped = NULL; switch (str[end]) { case '\r': escaped = "\\r"; break; case '\n': escaped = "\\n"; break; case '\\': escaped = "\\\\"; break; /* it is not required to escape a solidus in JSON: * read sec. 2.5: http://www.ietf.org/rfc/rfc4627.txt * specifically, this production from the grammar: * unescaped = %x20-21 / %x23-5B / %x5D-10FFFF */ case '/': if (escape_solidus) escaped = "\\/"; break; case '"': escaped = "\\\""; break; case '\f': escaped = "\\f"; break; case '\b': escaped = "\\b"; break; case '\t': escaped = "\\t"; break; default: if ((unsigned char) str[end] < 32) { CharToHex(str[end], hexBuf + 4); escaped = hexBuf; } break; } if (escaped != NULL) { print(ctx, (const char *) (str + beg), end - beg); print(ctx, escaped, (unsigned int)strlen(escaped)); beg = ++end; } else { ++end; } } print(ctx, (const char *) (str + beg), end - beg); } static void hexToDigit(unsigned int * val, const unsigned char * hex) { unsigned int i; for (i=0;i<4;i++) { unsigned char c = hex[i]; if (c >= 'A') c = (c & ~0x20) - 7; c -= '0'; assert(!(c & 0xF0)); *val = (*val << 4) | c; } } static void Utf32toUtf8(unsigned int codepoint, char * utf8Buf) { if (codepoint < 0x80) { utf8Buf[0] = (char) codepoint; utf8Buf[1] = 0; } else if (codepoint < 0x0800) { utf8Buf[0] = (char) ((codepoint >> 6) | 0xC0); utf8Buf[1] = (char) ((codepoint & 0x3F) | 0x80); utf8Buf[2] = 0; } else if (codepoint < 0x10000) { utf8Buf[0] = (char) ((codepoint >> 12) | 0xE0); utf8Buf[1] = (char) (((codepoint >> 6) & 0x3F) | 0x80); utf8Buf[2] = (char) ((codepoint & 0x3F) | 0x80); utf8Buf[3] = 0; } else if (codepoint < 0x200000) { utf8Buf[0] =(char)((codepoint >> 18) | 0xF0); utf8Buf[1] =(char)(((codepoint >> 12) & 0x3F) | 0x80); utf8Buf[2] =(char)(((codepoint >> 6) & 0x3F) | 0x80); utf8Buf[3] =(char)((codepoint & 0x3F) | 0x80); utf8Buf[4] = 0; } else { utf8Buf[0] = '?'; utf8Buf[1] = 0; } } void yajl_string_decode(yajl_buf buf, const unsigned char * str, size_t len) { size_t beg = 0; size_t end = 0; while (end < len) { if (str[end] == '\\') { char utf8Buf[5]; const char * unescaped = "?"; yajl_buf_append(buf, str + beg, end - beg); switch (str[++end]) { case 'r': unescaped = "\r"; break; case 'n': unescaped = "\n"; break; case '\\': unescaped = "\\"; break; case '/': unescaped = "/"; break; case '"': unescaped = "\""; break; case 'f': unescaped = "\f"; break; case 'b': unescaped = "\b"; break; case 't': unescaped = "\t"; break; case 'u': { unsigned int codepoint = 0; hexToDigit(&codepoint, str + ++end); end+=3; /* check if this is a surrogate */ if ((codepoint & 0xFC00) == 0xD800) { end++; if (str[end] == '\\' && str[end + 1] == 'u') { unsigned int surrogate = 0; hexToDigit(&surrogate, str + end + 2); codepoint = (((codepoint & 0x3F) << 10) | ((((codepoint >> 6) & 0xF) + 1) << 16) | (surrogate & 0x3FF)); end += 5; } else { unescaped = "?"; break; } } Utf32toUtf8(codepoint, utf8Buf); unescaped = utf8Buf; if (codepoint == 0) { yajl_buf_append(buf, unescaped, 1); beg = ++end; continue; } break; } default: assert("this should never happen" == NULL); } yajl_buf_append(buf, unescaped, (unsigned int)strlen(unescaped)); beg = ++end; } else { end++; } } yajl_buf_append(buf, str + beg, end - beg); } #define ADV_PTR s++; if (!(len--)) return 0; int yajl_string_validate_utf8(const unsigned char * s, size_t len) { if (!len) return 1; if (!s) return 0; while (len--) { /* single byte */ if (*s <= 0x7f) { /* noop */ } /* two byte */ else if ((*s >> 5) == 0x6) { ADV_PTR; if (!((*s >> 6) == 0x2)) return 0; } /* three byte */ else if ((*s >> 4) == 0x0e) { ADV_PTR; if (!((*s >> 6) == 0x2)) return 0; ADV_PTR; if (!((*s >> 6) == 0x2)) return 0; } /* four byte */ else if ((*s >> 3) == 0x1e) { ADV_PTR; if (!((*s >> 6) == 0x2)) return 0; ADV_PTR; if (!((*s >> 6) == 0x2)) return 0; ADV_PTR; if (!((*s >> 6) == 0x2)) return 0; } else { return 0; } s++; } return 1; } lnav-0.7.0/src/yajl/yajl_encode.h000664 000765 000024 00000002436 12211635054 017107 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __YAJL_ENCODE_H__ #define __YAJL_ENCODE_H__ #include "yajl_buf.h" #include "api/yajl_gen.h" void yajl_string_encode(const yajl_print_t printer, void * ctx, const unsigned char * str, size_t length, int escape_solidus); void yajl_string_decode(yajl_buf buf, const unsigned char * str, size_t length); int yajl_string_validate_utf8(const unsigned char * s, size_t len); #endif lnav-0.7.0/src/yajl/yajl_gen.c000664 000765 000024 00000024644 12211635054 016423 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "api/yajl_gen.h" #include "yajl_buf.h" #include "yajl_encode.h" #include #include #include #include #include typedef enum { yajl_gen_start, yajl_gen_map_start, yajl_gen_map_key, yajl_gen_map_val, yajl_gen_array_start, yajl_gen_in_array, yajl_gen_complete, yajl_gen_error } yajl_gen_state; struct yajl_gen_t { unsigned int flags; unsigned int depth; const char * indentString; yajl_gen_state state[YAJL_MAX_DEPTH]; yajl_print_t print; void * ctx; /* yajl_buf */ /* memory allocation routines */ yajl_alloc_funcs alloc; }; int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...) { int rv = 1; va_list ap; va_start(ap, opt); switch(opt) { case yajl_gen_beautify: case yajl_gen_validate_utf8: if (va_arg(ap, int)) g->flags |= opt; else g->flags &= ~opt; break; case yajl_gen_indent_string: { const char *indent = va_arg(ap, const char *); g->indentString = indent; for (; *indent; indent++) { if (*indent != '\n' && *indent != '\v' && *indent != '\f' && *indent != '\t' && *indent != '\r' && *indent != ' ') { g->indentString = NULL; rv = 0; } } break; } case yajl_gen_print_callback: yajl_buf_free(g->ctx); g->print = va_arg(ap, const yajl_print_t); g->ctx = va_arg(ap, void *); break; default: rv = 0; } va_end(ap); return rv; } yajl_gen yajl_gen_alloc(const yajl_alloc_funcs * afs) { yajl_gen g = NULL; yajl_alloc_funcs afsBuffer; /* first order of business is to set up memory allocation routines */ if (afs != NULL) { if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL) { return NULL; } } else { yajl_set_default_alloc_funcs(&afsBuffer); afs = &afsBuffer; } g = (yajl_gen) YA_MALLOC(afs, sizeof(struct yajl_gen_t)); if (!g) return NULL; memset((void *) g, 0, sizeof(struct yajl_gen_t)); /* copy in pointers to allocation routines */ memcpy((void *) &(g->alloc), (void *) afs, sizeof(yajl_alloc_funcs)); g->print = (yajl_print_t)&yajl_buf_append; g->ctx = yajl_buf_alloc(&(g->alloc)); g->indentString = " "; return g; } void yajl_gen_free(yajl_gen g) { if (g->print == (yajl_print_t)&yajl_buf_append) yajl_buf_free((yajl_buf)g->ctx); YA_FREE(&(g->alloc), g); } #define INSERT_SEP \ if (g->state[g->depth] == yajl_gen_map_key || \ g->state[g->depth] == yajl_gen_in_array) { \ g->print(g->ctx, ",", 1); \ if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); \ } else if (g->state[g->depth] == yajl_gen_map_val) { \ g->print(g->ctx, ":", 1); \ if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, " ", 1); \ } #define INSERT_WHITESPACE \ if ((g->flags & yajl_gen_beautify)) { \ if (g->state[g->depth] != yajl_gen_map_val) { \ unsigned int _i; \ for (_i=0;_idepth;_i++) \ g->print(g->ctx, \ g->indentString, \ (unsigned int)strlen(g->indentString)); \ } \ } #define ENSURE_NOT_KEY \ if (g->state[g->depth] == yajl_gen_map_key || \ g->state[g->depth] == yajl_gen_map_start) { \ return yajl_gen_keys_must_be_strings; \ } \ /* check that we're not complete, or in error state. in a valid state * to be generating */ #define ENSURE_VALID_STATE \ if (g->state[g->depth] == yajl_gen_error) { \ return yajl_gen_in_error_state;\ } else if (g->state[g->depth] == yajl_gen_complete) { \ return yajl_gen_generation_complete; \ } #define INCREMENT_DEPTH \ if (++(g->depth) >= YAJL_MAX_DEPTH) return yajl_max_depth_exceeded; #define DECREMENT_DEPTH \ if (--(g->depth) >= YAJL_MAX_DEPTH) return yajl_gen_error; #define APPENDED_ATOM \ switch (g->state[g->depth]) { \ case yajl_gen_start: \ g->state[g->depth] = yajl_gen_complete; \ break; \ case yajl_gen_map_start: \ case yajl_gen_map_key: \ g->state[g->depth] = yajl_gen_map_val; \ break; \ case yajl_gen_array_start: \ g->state[g->depth] = yajl_gen_in_array; \ break; \ case yajl_gen_map_val: \ g->state[g->depth] = yajl_gen_map_key; \ break; \ default: \ break; \ } \ #define FINAL_NEWLINE \ if ((g->flags & yajl_gen_beautify) && g->state[g->depth] == yajl_gen_complete) \ g->print(g->ctx, "\n", 1); yajl_gen_status yajl_gen_integer(yajl_gen g, long long int number) { char i[32]; ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; sprintf(i, "%lld", number); g->print(g->ctx, i, (unsigned int)strlen(i)); APPENDED_ATOM; FINAL_NEWLINE; return yajl_gen_status_ok; } #ifdef WIN32 #include #define isnan _isnan #define isinf !_finite #endif yajl_gen_status yajl_gen_double(yajl_gen g, double number) { char i[32]; ENSURE_VALID_STATE; ENSURE_NOT_KEY; if (isnan(number) || isinf(number)) return yajl_gen_invalid_number; INSERT_SEP; INSERT_WHITESPACE; sprintf(i, "%.20g", number); g->print(g->ctx, i, (unsigned int)strlen(i)); APPENDED_ATOM; FINAL_NEWLINE; return yajl_gen_status_ok; } yajl_gen_status yajl_gen_number(yajl_gen g, const char * s, size_t l) { ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; g->print(g->ctx, s, l); APPENDED_ATOM; FINAL_NEWLINE; return yajl_gen_status_ok; } yajl_gen_status yajl_gen_string(yajl_gen g, const unsigned char * str, size_t len) { // if validation is enabled, check that the string is valid utf8 // XXX: This checking could be done a little faster, in the same pass as // the string encoding if (g->flags & yajl_gen_validate_utf8) { if (!yajl_string_validate_utf8(str, len)) { return yajl_gen_invalid_string; } } ENSURE_VALID_STATE; INSERT_SEP; INSERT_WHITESPACE; g->print(g->ctx, "\"", 1); yajl_string_encode(g->print, g->ctx, str, len, g->flags & yajl_gen_escape_solidus); g->print(g->ctx, "\"", 1); APPENDED_ATOM; FINAL_NEWLINE; return yajl_gen_status_ok; } yajl_gen_status yajl_gen_null(yajl_gen g) { ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; g->print(g->ctx, "null", strlen("null")); APPENDED_ATOM; FINAL_NEWLINE; return yajl_gen_status_ok; } yajl_gen_status yajl_gen_bool(yajl_gen g, int boolean) { const char * val = boolean ? "true" : "false"; ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; g->print(g->ctx, val, (unsigned int)strlen(val)); APPENDED_ATOM; FINAL_NEWLINE; return yajl_gen_status_ok; } yajl_gen_status yajl_gen_map_open(yajl_gen g) { ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; INCREMENT_DEPTH; g->state[g->depth] = yajl_gen_map_start; g->print(g->ctx, "{", 1); if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); FINAL_NEWLINE; return yajl_gen_status_ok; } yajl_gen_status yajl_gen_map_close(yajl_gen g) { ENSURE_VALID_STATE; DECREMENT_DEPTH; if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); APPENDED_ATOM; INSERT_WHITESPACE; g->print(g->ctx, "}", 1); FINAL_NEWLINE; return yajl_gen_status_ok; } yajl_gen_status yajl_gen_array_open(yajl_gen g) { ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; INCREMENT_DEPTH; g->state[g->depth] = yajl_gen_array_start; g->print(g->ctx, "[", 1); if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); FINAL_NEWLINE; return yajl_gen_status_ok; } yajl_gen_status yajl_gen_array_close(yajl_gen g) { ENSURE_VALID_STATE; DECREMENT_DEPTH; if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); APPENDED_ATOM; INSERT_WHITESPACE; g->print(g->ctx, "]", 1); FINAL_NEWLINE; return yajl_gen_status_ok; } yajl_gen_status yajl_gen_get_buf(yajl_gen g, const unsigned char ** buf, size_t * len) { if (g->print != (yajl_print_t)&yajl_buf_append) return yajl_gen_no_buf; *buf = yajl_buf_data((yajl_buf)g->ctx); *len = yajl_buf_len((yajl_buf)g->ctx); return yajl_gen_status_ok; } void yajl_gen_clear(yajl_gen g) { if (g->print == (yajl_print_t)&yajl_buf_append) yajl_buf_clear((yajl_buf)g->ctx); } lnav-0.7.0/src/yajl/yajl_lex.c000664 000765 000024 00000063513 12211635054 016440 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "yajl_lex.h" #include "yajl_buf.h" #include #include #include #include #ifdef YAJL_LEXER_DEBUG static const char * tokToStr(yajl_tok tok) { switch (tok) { case yajl_tok_bool: return "bool"; case yajl_tok_colon: return "colon"; case yajl_tok_comma: return "comma"; case yajl_tok_eof: return "eof"; case yajl_tok_error: return "error"; case yajl_tok_left_brace: return "brace"; case yajl_tok_left_bracket: return "bracket"; case yajl_tok_null: return "null"; case yajl_tok_integer: return "integer"; case yajl_tok_double: return "double"; case yajl_tok_right_brace: return "brace"; case yajl_tok_right_bracket: return "bracket"; case yajl_tok_string: return "string"; case yajl_tok_string_with_escapes: return "string_with_escapes"; } return "unknown"; } #endif /* Impact of the stream parsing feature on the lexer: * * YAJL support stream parsing. That is, the ability to parse the first * bits of a chunk of JSON before the last bits are available (still on * the network or disk). This makes the lexer more complex. The * responsibility of the lexer is to handle transparently the case where * a chunk boundary falls in the middle of a token. This is * accomplished is via a buffer and a character reading abstraction. * * Overview of implementation * * When we lex to end of input string before end of token is hit, we * copy all of the input text composing the token into our lexBuf. * * Every time we read a character, we do so through the readChar function. * readChar's responsibility is to handle pulling all chars from the buffer * before pulling chars from input text */ struct yajl_lexer_t { /* the overal line and char offset into the data */ size_t lineOff; size_t charOff; /* error */ yajl_lex_error error; /* a input buffer to handle the case where a token is spread over * multiple chunks */ yajl_buf buf; /* in the case where we have data in the lexBuf, bufOff holds * the current offset into the lexBuf. */ size_t bufOff; /* are we using the lex buf? */ unsigned int bufInUse; /* shall we allow comments? */ unsigned int allowComments; /* shall we validate utf8 inside strings? */ unsigned int validateUTF8; yajl_alloc_funcs * alloc; }; #define readChar(lxr, txt, off) \ (((lxr)->bufInUse && yajl_buf_len((lxr)->buf) && lxr->bufOff < yajl_buf_len((lxr)->buf)) ? \ (*((const unsigned char *) yajl_buf_data((lxr)->buf) + ((lxr)->bufOff)++)) : \ ((txt)[(*(off))++])) #define unreadChar(lxr, off) ((*(off) > 0) ? (*(off))-- : ((lxr)->bufOff--)) yajl_lexer yajl_lex_alloc(yajl_alloc_funcs * alloc, unsigned int allowComments, unsigned int validateUTF8) { yajl_lexer lxr = (yajl_lexer) YA_MALLOC(alloc, sizeof(struct yajl_lexer_t)); memset((void *) lxr, 0, sizeof(struct yajl_lexer_t)); lxr->buf = yajl_buf_alloc(alloc); lxr->allowComments = allowComments; lxr->validateUTF8 = validateUTF8; lxr->alloc = alloc; return lxr; } void yajl_lex_free(yajl_lexer lxr) { yajl_buf_free(lxr->buf); YA_FREE(lxr->alloc, lxr); return; } /* a lookup table which lets us quickly determine three things: * VEC - valid escaped control char * note. the solidus '/' may be escaped or not. * IJC - invalid json char * VHC - valid hex char * NFP - needs further processing (from a string scanning perspective) * NUC - needs utf8 checking when enabled (from a string scanning perspective) */ #define VEC 0x01 #define IJC 0x02 #define VHC 0x04 #define NFP 0x08 #define NUC 0x10 static const char charLookupTable[256] = { /*00*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC , /*08*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC , /*10*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC , /*18*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC , /*20*/ 0 , 0 , NFP|VEC|IJC, 0 , 0 , 0 , 0 , 0 , /*28*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , VEC , /*30*/ VHC , VHC , VHC , VHC , VHC , VHC , VHC , VHC , /*38*/ VHC , VHC , 0 , 0 , 0 , 0 , 0 , 0 , /*40*/ 0 , VHC , VHC , VHC , VHC , VHC , VHC , 0 , /*48*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /*50*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , /*58*/ 0 , 0 , 0 , 0 , NFP|VEC|IJC, 0 , 0 , 0 , /*60*/ 0 , VHC , VEC|VHC, VHC , VHC , VHC , VEC|VHC, 0 , /*68*/ 0 , 0 , 0 , 0 , 0 , 0 , VEC , 0 , /*70*/ 0 , 0 , VEC , 0 , VEC , 0 , 0 , 0 , /*78*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC , NUC }; /** process a variable length utf8 encoded codepoint. * * returns: * yajl_tok_string - if valid utf8 char was parsed and offset was * advanced * yajl_tok_eof - if end of input was hit before validation could * complete * yajl_tok_error - if invalid utf8 was encountered * * NOTE: on error the offset will point to the first char of the * invalid utf8 */ #define UTF8_CHECK_EOF if (*offset >= jsonTextLen) { return yajl_tok_eof; } static yajl_tok yajl_lex_utf8_char(yajl_lexer lexer, const unsigned char * jsonText, size_t jsonTextLen, size_t * offset, unsigned char curChar) { if (curChar <= 0x7f) { /* single byte */ return yajl_tok_string; } else if ((curChar >> 5) == 0x6) { /* two byte */ UTF8_CHECK_EOF; curChar = readChar(lexer, jsonText, offset); if ((curChar >> 6) == 0x2) return yajl_tok_string; } else if ((curChar >> 4) == 0x0e) { /* three byte */ UTF8_CHECK_EOF; curChar = readChar(lexer, jsonText, offset); if ((curChar >> 6) == 0x2) { UTF8_CHECK_EOF; curChar = readChar(lexer, jsonText, offset); if ((curChar >> 6) == 0x2) return yajl_tok_string; } } else if ((curChar >> 3) == 0x1e) { /* four byte */ UTF8_CHECK_EOF; curChar = readChar(lexer, jsonText, offset); if ((curChar >> 6) == 0x2) { UTF8_CHECK_EOF; curChar = readChar(lexer, jsonText, offset); if ((curChar >> 6) == 0x2) { UTF8_CHECK_EOF; curChar = readChar(lexer, jsonText, offset); if ((curChar >> 6) == 0x2) return yajl_tok_string; } } } return yajl_tok_error; } /* lex a string. input is the lexer, pointer to beginning of * json text, and start of string (offset). * a token is returned which has the following meanings: * yajl_tok_string: lex of string was successful. offset points to * terminating '"'. * yajl_tok_eof: end of text was encountered before we could complete * the lex. * yajl_tok_error: embedded in the string were unallowable chars. offset * points to the offending char */ #define STR_CHECK_EOF \ if (*offset >= jsonTextLen) { \ tok = yajl_tok_eof; \ goto finish_string_lex; \ } /** scan a string for interesting characters that might need further * review. return the number of chars that are uninteresting and can * be skipped. * (lth) hi world, any thoughts on how to make this routine faster? */ static size_t yajl_string_scan(const unsigned char * buf, size_t len, int utf8check) { unsigned char mask = IJC|NFP|(utf8check ? NUC : 0); size_t skip = 0; while (skip < len && !(charLookupTable[*buf] & mask)) { skip++; buf++; } return skip; } static yajl_tok yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText, size_t jsonTextLen, size_t * offset) { yajl_tok tok = yajl_tok_error; int hasEscapes = 0; for (;;) { unsigned char curChar; /* now jump into a faster scanning routine to skip as much * of the buffers as possible */ { const unsigned char * p; size_t len; if ((lexer->bufInUse && yajl_buf_len(lexer->buf) && lexer->bufOff < yajl_buf_len(lexer->buf))) { p = ((const unsigned char *) yajl_buf_data(lexer->buf) + (lexer->bufOff)); len = yajl_buf_len(lexer->buf) - lexer->bufOff; lexer->bufOff += yajl_string_scan(p, len, lexer->validateUTF8); } else if (*offset < jsonTextLen) { p = jsonText + *offset; len = jsonTextLen - *offset; *offset += yajl_string_scan(p, len, lexer->validateUTF8); } } STR_CHECK_EOF; curChar = readChar(lexer, jsonText, offset); /* quote terminates */ if (curChar == '"') { tok = yajl_tok_string; break; } /* backslash escapes a set of control chars, */ else if (curChar == '\\') { hasEscapes = 1; STR_CHECK_EOF; /* special case \u */ curChar = readChar(lexer, jsonText, offset); if (curChar == 'u') { unsigned int i = 0; for (i=0;i<4;i++) { STR_CHECK_EOF; curChar = readChar(lexer, jsonText, offset); if (!(charLookupTable[curChar] & VHC)) { /* back up to offending char */ unreadChar(lexer, offset); lexer->error = yajl_lex_string_invalid_hex_char; goto finish_string_lex; } } } else if (!(charLookupTable[curChar] & VEC)) { /* back up to offending char */ unreadChar(lexer, offset); lexer->error = yajl_lex_string_invalid_escaped_char; goto finish_string_lex; } } /* when not validating UTF8 it's a simple table lookup to determine * if the present character is invalid */ else if(charLookupTable[curChar] & IJC) { /* back up to offending char */ unreadChar(lexer, offset); lexer->error = yajl_lex_string_invalid_json_char; goto finish_string_lex; } /* when in validate UTF8 mode we need to do some extra work */ else if (lexer->validateUTF8) { yajl_tok t = yajl_lex_utf8_char(lexer, jsonText, jsonTextLen, offset, curChar); if (t == yajl_tok_eof) { tok = yajl_tok_eof; goto finish_string_lex; } else if (t == yajl_tok_error) { lexer->error = yajl_lex_string_invalid_utf8; goto finish_string_lex; } } /* accept it, and move on */ } finish_string_lex: /* tell our buddy, the parser, wether he needs to process this string * again */ if (hasEscapes && tok == yajl_tok_string) { tok = yajl_tok_string_with_escapes; } return tok; } #define RETURN_IF_EOF if (*offset >= jsonTextLen) return yajl_tok_eof; static yajl_tok yajl_lex_number(yajl_lexer lexer, const unsigned char * jsonText, size_t jsonTextLen, size_t * offset) { /** XXX: numbers are the only entities in json that we must lex * _beyond_ in order to know that they are complete. There * is an ambiguous case for integers at EOF. */ unsigned char c; yajl_tok tok = yajl_tok_integer; RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); /* optional leading minus */ if (c == '-') { RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); } /* a single zero, or a series of integers */ if (c == '0') { RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); } else if (c >= '1' && c <= '9') { do { RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); } while (c >= '0' && c <= '9'); } else { unreadChar(lexer, offset); lexer->error = yajl_lex_missing_integer_after_minus; return yajl_tok_error; } /* optional fraction (indicates this is floating point) */ if (c == '.') { int numRd = 0; RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); while (c >= '0' && c <= '9') { numRd++; RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); } if (!numRd) { unreadChar(lexer, offset); lexer->error = yajl_lex_missing_integer_after_decimal; return yajl_tok_error; } tok = yajl_tok_double; } /* optional exponent (indicates this is floating point) */ if (c == 'e' || c == 'E') { RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); /* optional sign */ if (c == '+' || c == '-') { RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); } if (c >= '0' && c <= '9') { do { RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); } while (c >= '0' && c <= '9'); } else { unreadChar(lexer, offset); lexer->error = yajl_lex_missing_integer_after_exponent; return yajl_tok_error; } tok = yajl_tok_double; } /* we always go "one too far" */ unreadChar(lexer, offset); return tok; } static yajl_tok yajl_lex_comment(yajl_lexer lexer, const unsigned char * jsonText, size_t jsonTextLen, size_t * offset) { unsigned char c; yajl_tok tok = yajl_tok_comment; RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); /* either slash or star expected */ if (c == '/') { /* now we throw away until end of line */ do { RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); } while (c != '\n'); } else if (c == '*') { /* now we throw away until end of comment */ for (;;) { RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); if (c == '*') { RETURN_IF_EOF; c = readChar(lexer, jsonText, offset); if (c == '/') { break; } else { unreadChar(lexer, offset); } } } } else { lexer->error = yajl_lex_invalid_char; tok = yajl_tok_error; } return tok; } yajl_tok yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText, size_t jsonTextLen, size_t * offset, const unsigned char ** outBuf, size_t * outLen) { yajl_tok tok = yajl_tok_error; unsigned char c; size_t startOffset = *offset; *outBuf = NULL; *outLen = 0; for (;;) { assert(*offset <= jsonTextLen); if (*offset >= jsonTextLen) { tok = yajl_tok_eof; goto lexed; } c = readChar(lexer, jsonText, offset); switch (c) { case '{': tok = yajl_tok_left_bracket; goto lexed; case '}': tok = yajl_tok_right_bracket; goto lexed; case '[': tok = yajl_tok_left_brace; goto lexed; case ']': tok = yajl_tok_right_brace; goto lexed; case ',': tok = yajl_tok_comma; goto lexed; case ':': tok = yajl_tok_colon; goto lexed; case '\t': case '\n': case '\v': case '\f': case '\r': case ' ': startOffset++; break; case 't': { const char * want = "rue"; do { if (*offset >= jsonTextLen) { tok = yajl_tok_eof; goto lexed; } c = readChar(lexer, jsonText, offset); if (c != *want) { unreadChar(lexer, offset); lexer->error = yajl_lex_invalid_string; tok = yajl_tok_error; goto lexed; } } while (*(++want)); tok = yajl_tok_bool; goto lexed; } case 'f': { const char * want = "alse"; do { if (*offset >= jsonTextLen) { tok = yajl_tok_eof; goto lexed; } c = readChar(lexer, jsonText, offset); if (c != *want) { unreadChar(lexer, offset); lexer->error = yajl_lex_invalid_string; tok = yajl_tok_error; goto lexed; } } while (*(++want)); tok = yajl_tok_bool; goto lexed; } case 'n': { const char * want = "ull"; do { if (*offset >= jsonTextLen) { tok = yajl_tok_eof; goto lexed; } c = readChar(lexer, jsonText, offset); if (c != *want) { unreadChar(lexer, offset); lexer->error = yajl_lex_invalid_string; tok = yajl_tok_error; goto lexed; } } while (*(++want)); tok = yajl_tok_null; goto lexed; } case '"': { tok = yajl_lex_string(lexer, (const unsigned char *) jsonText, jsonTextLen, offset); goto lexed; } case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { /* integer parsing wants to start from the beginning */ unreadChar(lexer, offset); tok = yajl_lex_number(lexer, (const unsigned char *) jsonText, jsonTextLen, offset); goto lexed; } case '/': /* hey, look, a probable comment! If comments are disabled * it's an error. */ if (!lexer->allowComments) { unreadChar(lexer, offset); lexer->error = yajl_lex_unallowed_comment; tok = yajl_tok_error; goto lexed; } /* if comments are enabled, then we should try to lex * the thing. possible outcomes are * - successful lex (tok_comment, which means continue), * - malformed comment opening (slash not followed by * '*' or '/') (tok_error) * - eof hit. (tok_eof) */ tok = yajl_lex_comment(lexer, (const unsigned char *) jsonText, jsonTextLen, offset); if (tok == yajl_tok_comment) { /* "error" is silly, but that's the initial * state of tok. guilty until proven innocent. */ tok = yajl_tok_error; yajl_buf_clear(lexer->buf); lexer->bufInUse = 0; startOffset = *offset; break; } /* hit error or eof, bail */ goto lexed; default: lexer->error = yajl_lex_invalid_char; tok = yajl_tok_error; goto lexed; } } lexed: /* need to append to buffer if the buffer is in use or * if it's an EOF token */ if (tok == yajl_tok_eof || lexer->bufInUse) { if (!lexer->bufInUse) yajl_buf_clear(lexer->buf); lexer->bufInUse = 1; yajl_buf_append(lexer->buf, jsonText + startOffset, *offset - startOffset); lexer->bufOff = 0; if (tok != yajl_tok_eof) { *outBuf = yajl_buf_data(lexer->buf); *outLen = yajl_buf_len(lexer->buf); lexer->bufInUse = 0; } } else if (tok != yajl_tok_error) { *outBuf = jsonText + startOffset; *outLen = *offset - startOffset; } /* special case for strings. skip the quotes. */ if (tok == yajl_tok_string || tok == yajl_tok_string_with_escapes) { assert(*outLen >= 2); (*outBuf)++; *outLen -= 2; } #ifdef YAJL_LEXER_DEBUG if (tok == yajl_tok_error) { printf("lexical error: %s\n", yajl_lex_error_to_string(yajl_lex_get_error(lexer))); } else if (tok == yajl_tok_eof) { printf("EOF hit\n"); } else { printf("lexed %s: '", tokToStr(tok)); fwrite(*outBuf, 1, *outLen, stdout); printf("'\n"); } #endif return tok; } const char * yajl_lex_error_to_string(yajl_lex_error error) { switch (error) { case yajl_lex_e_ok: return "ok, no error"; case yajl_lex_string_invalid_utf8: return "invalid bytes in UTF8 string."; case yajl_lex_string_invalid_escaped_char: return "inside a string, '\\' occurs before a character " "which it may not."; case yajl_lex_string_invalid_json_char: return "invalid character inside string."; case yajl_lex_string_invalid_hex_char: return "invalid (non-hex) character occurs after '\\u' inside " "string."; case yajl_lex_invalid_char: return "invalid char in json text."; case yajl_lex_invalid_string: return "invalid string in json text."; case yajl_lex_missing_integer_after_exponent: return "malformed number, a digit is required after the exponent."; case yajl_lex_missing_integer_after_decimal: return "malformed number, a digit is required after the " "decimal point."; case yajl_lex_missing_integer_after_minus: return "malformed number, a digit is required after the " "minus sign."; case yajl_lex_unallowed_comment: return "probable comment found in input text, comments are " "not enabled."; } return "unknown error code"; } /** allows access to more specific information about the lexical * error when yajl_lex_lex returns yajl_tok_error. */ yajl_lex_error yajl_lex_get_error(yajl_lexer lexer) { if (lexer == NULL) return (yajl_lex_error) -1; return lexer->error; } size_t yajl_lex_current_line(yajl_lexer lexer) { return lexer->lineOff; } size_t yajl_lex_current_char(yajl_lexer lexer) { return lexer->charOff; } yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText, size_t jsonTextLen, size_t offset) { const unsigned char * outBuf; size_t outLen; size_t bufLen = yajl_buf_len(lexer->buf); size_t bufOff = lexer->bufOff; unsigned int bufInUse = lexer->bufInUse; yajl_tok tok; tok = yajl_lex_lex(lexer, jsonText, jsonTextLen, &offset, &outBuf, &outLen); lexer->bufOff = bufOff; lexer->bufInUse = bufInUse; yajl_buf_truncate(lexer->buf, bufLen); return tok; } lnav-0.7.0/src/yajl/yajl_lex.h000664 000765 000024 00000010201 12211635054 016427 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __YAJL_LEX_H__ #define __YAJL_LEX_H__ #include "api/yajl_common.h" typedef enum { yajl_tok_bool, yajl_tok_colon, yajl_tok_comma, yajl_tok_eof, yajl_tok_error, yajl_tok_left_brace, yajl_tok_left_bracket, yajl_tok_null, yajl_tok_right_brace, yajl_tok_right_bracket, /* we differentiate between integers and doubles to allow the * parser to interpret the number without re-scanning */ yajl_tok_integer, yajl_tok_double, /* we differentiate between strings which require further processing, * and strings that do not */ yajl_tok_string, yajl_tok_string_with_escapes, /* comment tokens are not currently returned to the parser, ever */ yajl_tok_comment } yajl_tok; typedef struct yajl_lexer_t * yajl_lexer; yajl_lexer yajl_lex_alloc(yajl_alloc_funcs * alloc, unsigned int allowComments, unsigned int validateUTF8); void yajl_lex_free(yajl_lexer lexer); /** * run/continue a lex. "offset" is an input/output parameter. * It should be initialized to zero for a * new chunk of target text, and upon subsetquent calls with the same * target text should passed with the value of the previous invocation. * * the client may be interested in the value of offset when an error is * returned from the lexer. This allows the client to render useful n * error messages. * * When you pass the next chunk of data, context should be reinitialized * to zero. * * Finally, the output buffer is usually just a pointer into the jsonText, * however in cases where the entity being lexed spans multiple chunks, * the lexer will buffer the entity and the data returned will be * a pointer into that buffer. * * This behavior is abstracted from client code except for the performance * implications which require that the client choose a reasonable chunk * size to get adequate performance. */ yajl_tok yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText, size_t jsonTextLen, size_t * offset, const unsigned char ** outBuf, size_t * outLen); /** have a peek at the next token, but don't move the lexer forward */ yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText, size_t jsonTextLen, size_t offset); typedef enum { yajl_lex_e_ok = 0, yajl_lex_string_invalid_utf8, yajl_lex_string_invalid_escaped_char, yajl_lex_string_invalid_json_char, yajl_lex_string_invalid_hex_char, yajl_lex_invalid_char, yajl_lex_invalid_string, yajl_lex_missing_integer_after_decimal, yajl_lex_missing_integer_after_exponent, yajl_lex_missing_integer_after_minus, yajl_lex_unallowed_comment } yajl_lex_error; const char * yajl_lex_error_to_string(yajl_lex_error error); /** allows access to more specific information about the lexical * error when yajl_lex_lex returns yajl_tok_error. */ yajl_lex_error yajl_lex_get_error(yajl_lexer lexer); /** get the current offset into the most recently lexed json string. */ size_t yajl_lex_current_offset(yajl_lexer lexer); /** get the number of lines lexed by this lexer instance */ size_t yajl_lex_current_line(yajl_lexer lexer); /** get the number of chars lexed by this lexer instance since the last * \n or \r */ size_t yajl_lex_current_char(yajl_lexer lexer); #endif lnav-0.7.0/src/yajl/yajl_parser.c000664 000765 000024 00000047703 12211635054 017147 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include "api/yajl_parse.h" #include "yajl_lex.h" #include "yajl_parser.h" #include "yajl_encode.h" #include "yajl_bytestack.h" #include #include #include #include #include #include #include #include #define MAX_VALUE_TO_MULTIPLY ((LLONG_MAX / 10) + (LLONG_MAX % 10)) /* same semantics as strtol */ long long yajl_parse_integer(const unsigned char *number, unsigned int length) { long long ret = 0; long sign = 1; const unsigned char *pos = number; if (*pos == '-') { pos++; sign = -1; } if (*pos == '+') { pos++; } while (pos < number + length) { if ( ret > MAX_VALUE_TO_MULTIPLY ) { errno = ERANGE; return sign == 1 ? LLONG_MAX : LLONG_MIN; } ret *= 10; if (LLONG_MAX - ret < (*pos - '0')) { errno = ERANGE; return sign == 1 ? LLONG_MAX : LLONG_MIN; } ret += (*pos++ - '0'); } return sign * ret; } unsigned char * yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, size_t jsonTextLen, int verbose) { size_t offset = hand->bytesConsumed; unsigned char * str; const char * errorType = NULL; const char * errorText = NULL; char text[72]; const char * arrow = " (right here) ------^\n"; if (yajl_bs_current(hand->stateStack) == yajl_state_parse_error) { errorType = "parse"; errorText = hand->parseError; } else if (yajl_bs_current(hand->stateStack) == yajl_state_lexical_error) { errorType = "lexical"; errorText = yajl_lex_error_to_string(yajl_lex_get_error(hand->lexer)); } else { errorType = "unknown"; } { size_t memneeded = 0; memneeded += strlen(errorType); memneeded += strlen(" error"); if (errorText != NULL) { memneeded += strlen(": "); memneeded += strlen(errorText); } str = (unsigned char *) YA_MALLOC(&(hand->alloc), memneeded + 2); if (!str) return NULL; str[0] = 0; strcat((char *) str, errorType); strcat((char *) str, " error"); if (errorText != NULL) { strcat((char *) str, ": "); strcat((char *) str, errorText); } strcat((char *) str, "\n"); } /* now we append as many spaces as needed to make sure the error * falls at char 41, if verbose was specified */ if (verbose) { size_t start, end, i; size_t spacesNeeded; spacesNeeded = (offset < 30 ? 40 - offset : 10); start = (offset >= 30 ? offset - 30 : 0); end = (offset + 30 > jsonTextLen ? jsonTextLen : offset + 30); for (i=0;ialloc), (unsigned int)(strlen((char *) str) + strlen((char *) text) + strlen(arrow) + 1)); if (newStr) { newStr[0] = 0; strcat((char *) newStr, (char *) str); strcat((char *) newStr, text); strcat((char *) newStr, arrow); } YA_FREE(&(hand->alloc), str); str = (unsigned char *) newStr; } } return str; } /* check for client cancelation */ #define _CC_CHK(x) \ if (!(x)) { \ yajl_bs_set(hand->stateStack, yajl_state_parse_error); \ hand->parseError = \ "client cancelled parse via callback return value"; \ return yajl_status_client_canceled; \ } yajl_status yajl_do_finish(yajl_handle hand) { yajl_status stat; stat = yajl_do_parse(hand,(const unsigned char *) " ",1); if (stat != yajl_status_ok) return stat; switch(yajl_bs_current(hand->stateStack)) { case yajl_state_parse_error: case yajl_state_lexical_error: return yajl_status_error; case yajl_state_got_value: case yajl_state_parse_complete: return yajl_status_ok; default: if (!(hand->flags & yajl_allow_partial_values)) { yajl_bs_set(hand->stateStack, yajl_state_parse_error); hand->parseError = "premature EOF"; return yajl_status_error; } return yajl_status_ok; } } yajl_status yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, size_t jsonTextLen) { yajl_tok tok; const unsigned char * buf; size_t bufLen; size_t * offset = &(hand->bytesConsumed); *offset = 0; around_again: switch (yajl_bs_current(hand->stateStack)) { case yajl_state_parse_complete: if (hand->flags & yajl_allow_multiple_values) { yajl_bs_set(hand->stateStack, yajl_state_got_value); goto around_again; } if (!(hand->flags & yajl_allow_trailing_garbage)) { if (*offset != jsonTextLen) { tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, offset, &buf, &bufLen); if (tok != yajl_tok_eof) { yajl_bs_set(hand->stateStack, yajl_state_parse_error); hand->parseError = "trailing garbage"; } goto around_again; } } return yajl_status_ok; case yajl_state_lexical_error: case yajl_state_parse_error: return yajl_status_error; case yajl_state_start: case yajl_state_got_value: case yajl_state_map_need_val: case yajl_state_array_need_val: case yajl_state_array_start: { /* for arrays and maps, we advance the state for this * depth, then push the state of the next depth. * If an error occurs during the parsing of the nesting * enitity, the state at this level will not matter. * a state that needs pushing will be anything other * than state_start */ yajl_state stateToPush = yajl_state_start; tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, offset, &buf, &bufLen); switch (tok) { case yajl_tok_eof: return yajl_status_ok; case yajl_tok_error: yajl_bs_set(hand->stateStack, yajl_state_lexical_error); goto around_again; case yajl_tok_string: if (hand->callbacks && hand->callbacks->yajl_string) { _CC_CHK(hand->callbacks->yajl_string(hand->ctx, buf, bufLen)); } break; case yajl_tok_string_with_escapes: if (hand->callbacks && hand->callbacks->yajl_string) { yajl_buf_clear(hand->decodeBuf); yajl_string_decode(hand->decodeBuf, buf, bufLen); _CC_CHK(hand->callbacks->yajl_string( hand->ctx, yajl_buf_data(hand->decodeBuf), yajl_buf_len(hand->decodeBuf))); } break; case yajl_tok_bool: if (hand->callbacks && hand->callbacks->yajl_boolean) { _CC_CHK(hand->callbacks->yajl_boolean(hand->ctx, *buf == 't')); } break; case yajl_tok_null: if (hand->callbacks && hand->callbacks->yajl_null) { _CC_CHK(hand->callbacks->yajl_null(hand->ctx)); } break; case yajl_tok_left_bracket: if (hand->callbacks && hand->callbacks->yajl_start_map) { _CC_CHK(hand->callbacks->yajl_start_map(hand->ctx)); } stateToPush = yajl_state_map_start; break; case yajl_tok_left_brace: if (hand->callbacks && hand->callbacks->yajl_start_array) { _CC_CHK(hand->callbacks->yajl_start_array(hand->ctx)); } stateToPush = yajl_state_array_start; break; case yajl_tok_integer: if (hand->callbacks) { if (hand->callbacks->yajl_number) { _CC_CHK(hand->callbacks->yajl_number( hand->ctx,(const char *) buf, bufLen)); } else if (hand->callbacks->yajl_integer) { long long int i = 0; i = yajl_parse_integer(buf, bufLen); if ((i == LLONG_MIN || i == LLONG_MAX) && errno == ERANGE) { yajl_bs_set(hand->stateStack, yajl_state_parse_error); hand->parseError = "integer overflow" ; /* try to restore error offset */ if (*offset >= bufLen) *offset -= bufLen; else *offset = 0; goto around_again; } _CC_CHK(hand->callbacks->yajl_integer(hand->ctx, i)); } } break; case yajl_tok_double: if (hand->callbacks) { if (hand->callbacks->yajl_number) { _CC_CHK(hand->callbacks->yajl_number( hand->ctx, (const char *) buf, bufLen)); } else if (hand->callbacks->yajl_double) { double d = 0.0; yajl_buf_clear(hand->decodeBuf); yajl_buf_append(hand->decodeBuf, buf, bufLen); buf = yajl_buf_data(hand->decodeBuf); d = strtod((char *) buf, NULL); if ((d == HUGE_VAL || d == -HUGE_VAL) && errno == ERANGE) { yajl_bs_set(hand->stateStack, yajl_state_parse_error); hand->parseError = "numeric (floating point) " "overflow"; /* try to restore error offset */ if (*offset >= bufLen) *offset -= bufLen; else *offset = 0; goto around_again; } _CC_CHK(hand->callbacks->yajl_double(hand->ctx, d)); } } break; case yajl_tok_right_brace: { if (yajl_bs_current(hand->stateStack) == yajl_state_array_start) { if (hand->callbacks && hand->callbacks->yajl_end_array) { _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx)); } yajl_bs_pop(hand->stateStack); goto around_again; } /* intentional fall-through */ } case yajl_tok_colon: case yajl_tok_comma: case yajl_tok_right_bracket: yajl_bs_set(hand->stateStack, yajl_state_parse_error); hand->parseError = "unallowed token at this point in JSON text"; goto around_again; default: yajl_bs_set(hand->stateStack, yajl_state_parse_error); hand->parseError = "invalid token, internal error"; goto around_again; } /* got a value. transition depends on the state we're in. */ { yajl_state s = yajl_bs_current(hand->stateStack); if (s == yajl_state_start || s == yajl_state_got_value) { yajl_bs_set(hand->stateStack, yajl_state_parse_complete); } else if (s == yajl_state_map_need_val) { yajl_bs_set(hand->stateStack, yajl_state_map_got_val); } else { yajl_bs_set(hand->stateStack, yajl_state_array_got_val); } } if (stateToPush != yajl_state_start) { yajl_bs_push(hand->stateStack, stateToPush); } goto around_again; } case yajl_state_map_start: case yajl_state_map_need_key: { /* only difference between these two states is that in * start '}' is valid, whereas in need_key, we've parsed * a comma, and a string key _must_ follow */ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, offset, &buf, &bufLen); switch (tok) { case yajl_tok_eof: return yajl_status_ok; case yajl_tok_error: yajl_bs_set(hand->stateStack, yajl_state_lexical_error); goto around_again; case yajl_tok_string_with_escapes: if (hand->callbacks && hand->callbacks->yajl_map_key) { yajl_buf_clear(hand->decodeBuf); yajl_string_decode(hand->decodeBuf, buf, bufLen); buf = yajl_buf_data(hand->decodeBuf); bufLen = yajl_buf_len(hand->decodeBuf); } /* intentional fall-through */ case yajl_tok_string: if (hand->callbacks && hand->callbacks->yajl_map_key) { _CC_CHK(hand->callbacks->yajl_map_key(hand->ctx, buf, bufLen)); } yajl_bs_set(hand->stateStack, yajl_state_map_sep); goto around_again; case yajl_tok_right_bracket: if (yajl_bs_current(hand->stateStack) == yajl_state_map_start) { if (hand->callbacks && hand->callbacks->yajl_end_map) { _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx)); } yajl_bs_pop(hand->stateStack); goto around_again; } default: yajl_bs_set(hand->stateStack, yajl_state_parse_error); hand->parseError = "invalid object key (must be a string)"; goto around_again; } } case yajl_state_map_sep: { tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, offset, &buf, &bufLen); switch (tok) { case yajl_tok_colon: yajl_bs_set(hand->stateStack, yajl_state_map_need_val); goto around_again; case yajl_tok_eof: return yajl_status_ok; case yajl_tok_error: yajl_bs_set(hand->stateStack, yajl_state_lexical_error); goto around_again; default: yajl_bs_set(hand->stateStack, yajl_state_parse_error); hand->parseError = "object key and value must " "be separated by a colon (':')"; goto around_again; } } case yajl_state_map_got_val: { tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, offset, &buf, &bufLen); switch (tok) { case yajl_tok_right_bracket: if (hand->callbacks && hand->callbacks->yajl_end_map) { _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx)); } yajl_bs_pop(hand->stateStack); goto around_again; case yajl_tok_comma: yajl_bs_set(hand->stateStack, yajl_state_map_need_key); goto around_again; case yajl_tok_eof: return yajl_status_ok; case yajl_tok_error: yajl_bs_set(hand->stateStack, yajl_state_lexical_error); goto around_again; default: yajl_bs_set(hand->stateStack, yajl_state_parse_error); hand->parseError = "after key and value, inside map, " "I expect ',' or '}'"; /* try to restore error offset */ if (*offset >= bufLen) *offset -= bufLen; else *offset = 0; goto around_again; } } case yajl_state_array_got_val: { tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, offset, &buf, &bufLen); switch (tok) { case yajl_tok_right_brace: if (hand->callbacks && hand->callbacks->yajl_end_array) { _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx)); } yajl_bs_pop(hand->stateStack); goto around_again; case yajl_tok_comma: yajl_bs_set(hand->stateStack, yajl_state_array_need_val); goto around_again; case yajl_tok_eof: return yajl_status_ok; case yajl_tok_error: yajl_bs_set(hand->stateStack, yajl_state_lexical_error); goto around_again; default: yajl_bs_set(hand->stateStack, yajl_state_parse_error); hand->parseError = "after array element, I expect ',' or ']'"; goto around_again; } } } abort(); return yajl_status_error; } lnav-0.7.0/src/yajl/yajl_parser.h000664 000765 000024 00000004706 12211635054 017150 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __YAJL_PARSER_H__ #define __YAJL_PARSER_H__ #include "api/yajl_parse.h" #include "yajl_bytestack.h" #include "yajl_buf.h" #include "yajl_lex.h" typedef enum { yajl_state_start = 0, yajl_state_parse_complete, yajl_state_parse_error, yajl_state_lexical_error, yajl_state_map_start, yajl_state_map_sep, yajl_state_map_need_val, yajl_state_map_got_val, yajl_state_map_need_key, yajl_state_array_start, yajl_state_array_got_val, yajl_state_array_need_val, yajl_state_got_value, } yajl_state; struct yajl_handle_t { const yajl_callbacks * callbacks; void * ctx; yajl_lexer lexer; const char * parseError; /* the number of bytes consumed from the last client buffer, * in the case of an error this will be an error offset, in the * case of an error this can be used as the error offset */ size_t bytesConsumed; /* temporary storage for decoded strings */ yajl_buf decodeBuf; /* a stack of states. access with yajl_state_XXX routines */ yajl_bytestack stateStack; /* memory allocation routines */ yajl_alloc_funcs alloc; /* bitfield */ unsigned int flags; }; yajl_status yajl_do_parse(yajl_handle handle, const unsigned char * jsonText, size_t jsonTextLen); yajl_status yajl_do_finish(yajl_handle handle); unsigned char * yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, size_t jsonTextLen, int verbose); /* A little built in integer parsing routine with the same semantics as strtol * that's unaffected by LOCALE. */ long long yajl_parse_integer(const unsigned char *number, unsigned int length); #endif lnav-0.7.0/src/yajl/._yajl_tree.c000664 000765 000024 00000000253 12311034247 017012 0ustar00stackstaff000000 000000 Mac OS X  2y«ATTR«œœcom.apple.TextEncodingutf-8;134217984lnav-0.7.0/src/yajl/yajl_tree.c000664 000765 000024 00000032513 12311034247 016601 0ustar00stackstaff000000 000000 /* * Copyright (c) 2010-2011 Florian Forster * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include "api/yajl_tree.h" #include "api/yajl_parse.h" #include "yajl_parser.h" #ifdef WIN32 #define snprintf sprintf_s #endif #define STATUS_CONTINUE 1 #define STATUS_ABORT 0 struct stack_elem_s; typedef struct stack_elem_s stack_elem_t; struct stack_elem_s { char * key; yajl_val value; stack_elem_t *next; }; struct context_s { stack_elem_t *stack; yajl_val root; char *errbuf; size_t errbuf_size; }; typedef struct context_s context_t; #define RETURN_ERROR(ctx,retval,...) { \ if ((ctx)->errbuf != NULL) \ snprintf ((ctx)->errbuf, (ctx)->errbuf_size, __VA_ARGS__); \ return (retval); \ } static yajl_val value_alloc (yajl_type type) { yajl_val v; v = malloc (sizeof (*v)); if (v == NULL) return (NULL); memset (v, 0, sizeof (*v)); v->type = type; return (v); } static void yajl_object_free (yajl_val v) { size_t i; if (!YAJL_IS_OBJECT(v)) return; for (i = 0; i < v->u.object.len; i++) { free((char *) v->u.object.keys[i]); v->u.object.keys[i] = NULL; yajl_tree_free (v->u.object.values[i]); v->u.object.values[i] = NULL; } free((void*) v->u.object.keys); free(v->u.object.values); free(v); } static void yajl_array_free (yajl_val v) { size_t i; if (!YAJL_IS_ARRAY(v)) return; for (i = 0; i < v->u.array.len; i++) { yajl_tree_free (v->u.array.values[i]); v->u.array.values[i] = NULL; } free(v->u.array.values); free(v); } /* * Parsing nested objects and arrays is implemented using a stack. When a new * object or array starts (a curly or a square opening bracket is read), an * appropriate value is pushed on the stack. When the end of the object is * reached (an appropriate closing bracket has been read), the value is popped * off the stack and added to the enclosing object using "context_add_value". */ static int context_push(context_t *ctx, yajl_val v) { stack_elem_t *stack; stack = malloc (sizeof (*stack)); if (stack == NULL) RETURN_ERROR (ctx, ENOMEM, "Out of memory"); memset (stack, 0, sizeof (*stack)); assert ((ctx->stack == NULL) || YAJL_IS_OBJECT (v) || YAJL_IS_ARRAY (v)); stack->value = v; stack->next = ctx->stack; ctx->stack = stack; return (0); } static yajl_val context_pop(context_t *ctx) { stack_elem_t *stack; yajl_val v; if (ctx->stack == NULL) RETURN_ERROR (ctx, NULL, "context_pop: " "Bottom of stack reached prematurely"); stack = ctx->stack; ctx->stack = stack->next; v = stack->value; free (stack); return (v); } static int object_add_keyval(context_t *ctx, yajl_val obj, char *key, yajl_val value) { const char **tmpk; yajl_val *tmpv; /* We're checking for NULL in "context_add_value" or its callers. */ assert (ctx != NULL); assert (obj != NULL); assert (key != NULL); assert (value != NULL); /* We're assuring that "obj" is an object in "context_add_value". */ assert(YAJL_IS_OBJECT(obj)); tmpk = realloc((void *) obj->u.object.keys, sizeof(*(obj->u.object.keys)) * (obj->u.object.len + 1)); if (tmpk == NULL) RETURN_ERROR(ctx, ENOMEM, "Out of memory"); obj->u.object.keys = tmpk; tmpv = realloc(obj->u.object.values, sizeof (*obj->u.object.values) * (obj->u.object.len + 1)); if (tmpv == NULL) RETURN_ERROR(ctx, ENOMEM, "Out of memory"); obj->u.object.values = tmpv; obj->u.object.keys[obj->u.object.len] = key; obj->u.object.values[obj->u.object.len] = value; obj->u.object.len++; return (0); } static int array_add_value (context_t *ctx, yajl_val array, yajl_val value) { yajl_val *tmp; /* We're checking for NULL pointers in "context_add_value" or its * callers. */ assert (ctx != NULL); assert (array != NULL); assert (value != NULL); /* "context_add_value" will only call us with array values. */ assert(YAJL_IS_ARRAY(array)); tmp = realloc(array->u.array.values, sizeof(*(array->u.array.values)) * (array->u.array.len + 1)); if (tmp == NULL) RETURN_ERROR(ctx, ENOMEM, "Out of memory"); array->u.array.values = tmp; array->u.array.values[array->u.array.len] = value; array->u.array.len++; return 0; } /* * Add a value to the value on top of the stack or the "root" member in the * context if the end of the parsing process is reached. */ static int context_add_value (context_t *ctx, yajl_val v) { /* We're checking for NULL values in all the calling functions. */ assert (ctx != NULL); assert (v != NULL); /* * There are three valid states in which this function may be called: * - There is no value on the stack => This is the only value. This is the * last step done when parsing a document. We assign the value to the * "root" member and return. * - The value on the stack is an object. In this case store the key on the * stack or, if the key has already been read, add key and value to the * object. * - The value on the stack is an array. In this case simply add the value * and return. */ if (ctx->stack == NULL) { assert (ctx->root == NULL); ctx->root = v; return (0); } else if (YAJL_IS_OBJECT (ctx->stack->value)) { if (ctx->stack->key == NULL) { if (!YAJL_IS_STRING (v)) RETURN_ERROR (ctx, EINVAL, "context_add_value: " "Object key is not a string (%#04x)", v->type); ctx->stack->key = v->u.string; v->u.string = NULL; free(v); return (0); } else /* if (ctx->key != NULL) */ { char * key; key = ctx->stack->key; ctx->stack->key = NULL; return (object_add_keyval (ctx, ctx->stack->value, key, v)); } } else if (YAJL_IS_ARRAY (ctx->stack->value)) { return (array_add_value (ctx, ctx->stack->value, v)); } else { RETURN_ERROR (ctx, EINVAL, "context_add_value: Cannot add value to " "a value of type %#04x (not a composite type)", ctx->stack->value->type); } } static int handle_string (void *ctx, const unsigned char *string, size_t string_length) { yajl_val v; v = value_alloc (yajl_t_string); if (v == NULL) RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); v->u.string = malloc (string_length + 1); if (v->u.string == NULL) { free (v); RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); } memcpy(v->u.string, string, string_length); v->u.string[string_length] = 0; return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); } static int handle_number (void *ctx, const char *string, size_t string_length) { yajl_val v; char *endptr; v = value_alloc(yajl_t_number); if (v == NULL) RETURN_ERROR((context_t *) ctx, STATUS_ABORT, "Out of memory"); v->u.number.r = malloc(string_length + 1); if (v->u.number.r == NULL) { free(v); RETURN_ERROR((context_t *) ctx, STATUS_ABORT, "Out of memory"); } memcpy(v->u.number.r, string, string_length); v->u.number.r[string_length] = 0; v->u.number.flags = 0; endptr = NULL; errno = 0; v->u.number.i = yajl_parse_integer((const unsigned char *) v->u.number.r, strlen(v->u.number.r)); if ((errno == 0) && (endptr != NULL) && (*endptr == 0)) v->u.number.flags |= YAJL_NUMBER_INT_VALID; endptr = NULL; errno = 0; v->u.number.d = strtod(v->u.number.r, &endptr); if ((errno == 0) && (endptr != NULL) && (*endptr == 0)) v->u.number.flags |= YAJL_NUMBER_DOUBLE_VALID; return ((context_add_value(ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); } static int handle_start_map (void *ctx) { yajl_val v; v = value_alloc(yajl_t_object); if (v == NULL) RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); v->u.object.keys = NULL; v->u.object.values = NULL; v->u.object.len = 0; return ((context_push (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); } static int handle_end_map (void *ctx) { yajl_val v; v = context_pop (ctx); if (v == NULL) return (STATUS_ABORT); return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); } static int handle_start_array (void *ctx) { yajl_val v; v = value_alloc(yajl_t_array); if (v == NULL) RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); v->u.array.values = NULL; v->u.array.len = 0; return ((context_push (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); } static int handle_end_array (void *ctx) { yajl_val v; v = context_pop (ctx); if (v == NULL) return (STATUS_ABORT); return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); } static int handle_boolean (void *ctx, int boolean_value) { yajl_val v; v = value_alloc (boolean_value ? yajl_t_true : yajl_t_false); if (v == NULL) RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); } static int handle_null (void *ctx) { yajl_val v; v = value_alloc (yajl_t_null); if (v == NULL) RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); } /* * Public functions */ yajl_val yajl_tree_parse (const char *input, char *error_buffer, size_t error_buffer_size) { static const yajl_callbacks callbacks = { /* null = */ handle_null, /* boolean = */ handle_boolean, /* integer = */ NULL, /* double = */ NULL, /* number = */ handle_number, /* string = */ handle_string, /* start map = */ handle_start_map, /* map key = */ handle_string, /* end map = */ handle_end_map, /* start array = */ handle_start_array, /* end array = */ handle_end_array }; yajl_handle handle; yajl_status status; context_t ctx = { NULL, NULL, NULL, 0 }; ctx.errbuf = error_buffer; ctx.errbuf_size = error_buffer_size; if (error_buffer != NULL) memset (error_buffer, 0, error_buffer_size); handle = yajl_alloc (&callbacks, NULL, &ctx); yajl_config(handle, yajl_allow_comments, 1); status = yajl_parse(handle, (unsigned char *) input, strlen (input)); status = yajl_complete_parse (handle); if (status != yajl_status_ok) { if (error_buffer != NULL && error_buffer_size > 0) { snprintf( error_buffer, error_buffer_size, "%s", (char *) yajl_get_error(handle, 1, (const unsigned char *) input, strlen(input))); } yajl_free (handle); return NULL; } yajl_free (handle); return (ctx.root); } yajl_val yajl_tree_get(yajl_val n, const char ** path, yajl_type type) { if (!path) return NULL; while (n && *path) { unsigned int i; if (n->type != yajl_t_object) return NULL; for (i = 0; i < n->u.object.len; i++) { if (!strcmp(*path, n->u.object.keys[i])) { n = n->u.object.values[i]; break; } } if (i == n->u.object.len) return NULL; path++; } if (n && type != yajl_t_any && type != n->type) n = NULL; return n; } void yajl_tree_free (yajl_val v) { if (v == NULL) return; if (YAJL_IS_STRING(v)) { free(v->u.string); free(v); } else if (YAJL_IS_NUMBER(v)) { free(v->u.number.r); free(v); } else if (YAJL_GET_OBJECT(v)) { yajl_object_free(v); } else if (YAJL_GET_ARRAY(v)) { yajl_array_free(v); } else /* if (yajl_t_true or yajl_t_false or yajl_t_null) */ { free(v); } } lnav-0.7.0/src/yajl/yajl_version.c000664 000765 000024 00000000122 12211635054 017320 0ustar00stackstaff000000 000000 #include int yajl_version(void) { return YAJL_VERSION; } lnav-0.7.0/src/yajl/yajl_version.h000664 000765 000024 00000000553 12211635054 017335 0ustar00stackstaff000000 000000 #ifndef YAJL_VERSION_H_ #define YAJL_VERSION_H_ #include #define YAJL_MAJOR 2 #define YAJL_MINOR 0 #define YAJL_MICRO 1 #define YAJL_VERSION ((YAJL_MAJOR * 10000) + (YAJL_MINOR * 100) + YAJL_MICRO) #ifdef __cplusplus extern "C" { #endif extern int YAJL_API yajl_version(void); #ifdef __cplusplus } #endif #endif /* YAJL_VERSION_H_ */ lnav-0.7.0/src/yajl/api/yajl_common.h000664 000765 000024 00000005002 12211635054 017703 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef __YAJL_COMMON_H__ #define __YAJL_COMMON_H__ #include #ifdef __cplusplus extern "C" { #endif #define YAJL_MAX_DEPTH 128 /* msft dll export gunk. To build a DLL on windows, you * must define WIN32, YAJL_SHARED, and YAJL_BUILD. To use a shared * DLL, you must define YAJL_SHARED and WIN32 */ #if defined(WIN32) && defined(YAJL_SHARED) # ifdef YAJL_BUILD # define YAJL_API __declspec(dllexport) # else # define YAJL_API __declspec(dllimport) # endif #else # if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303 # define YAJL_API __attribute__ ((visibility("default"))) # else # define YAJL_API # endif #endif /** pointer to a malloc function, supporting client overriding memory * allocation routines */ typedef void * (*yajl_malloc_func)(void *ctx, size_t sz); /** pointer to a free function, supporting client overriding memory * allocation routines */ typedef void (*yajl_free_func)(void *ctx, void * ptr); /** pointer to a realloc function which can resize an allocation. */ typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, size_t sz); /** A structure which can be passed to yajl_*_alloc routines to allow the * client to specify memory allocation functions to be used. */ typedef struct { /** pointer to a function that can allocate uninitialized memory */ yajl_malloc_func malloc; /** pointer to a function that can resize memory allocations */ yajl_realloc_func realloc; /** pointer to a function that can free memory allocated using * reallocFunction or mallocFunction */ yajl_free_func free; /** a context pointer that will be passed to above allocation routines */ void * ctx; } yajl_alloc_funcs; #ifdef __cplusplus } #endif #endif lnav-0.7.0/src/yajl/api/yajl_gen.h000664 000765 000024 00000014761 12211635054 017200 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * \file yajl_gen.h * Interface to YAJL's JSON generation facilities. */ #include #ifndef __YAJL_GEN_H__ #define __YAJL_GEN_H__ #include #ifdef __cplusplus extern "C" { #endif /** generator status codes */ typedef enum { /** no error */ yajl_gen_status_ok = 0, /** at a point where a map key is generated, a function other than * yajl_gen_string was called */ yajl_gen_keys_must_be_strings, /** YAJL's maximum generation depth was exceeded. see * YAJL_MAX_DEPTH */ yajl_max_depth_exceeded, /** A generator function (yajl_gen_XXX) was called while in an error * state */ yajl_gen_in_error_state, /** A complete JSON document has been generated */ yajl_gen_generation_complete, /** yajl_gen_double was passed an invalid floating point value * (infinity or NaN). */ yajl_gen_invalid_number, /** A print callback was passed in, so there is no internal * buffer to get from */ yajl_gen_no_buf, /** returned from yajl_gen_string() when the yajl_gen_validate_utf8 * option is enabled and an invalid was passed by client code. */ yajl_gen_invalid_string } yajl_gen_status; /** an opaque handle to a generator */ typedef struct yajl_gen_t * yajl_gen; /** a callback used for "printing" the results. */ typedef void (*yajl_print_t)(void * ctx, const char * str, size_t len); /** configuration parameters for the parser, these may be passed to * yajl_gen_config() along with option specific argument(s). In general, * all configuration parameters default to *off*. */ typedef enum { /** generate indented (beautiful) output */ yajl_gen_beautify = 0x01, /** * Set an indent string which is used when yajl_gen_beautify * is enabled. Maybe something like \\t or some number of * spaces. The default is four spaces ' '. */ yajl_gen_indent_string = 0x02, /** * Set a function and context argument that should be used to * output generated json. the function should conform to the * yajl_print_t prototype while the context argument is a * void * of your choosing. * * example: * yajl_gen_config(g, yajl_gen_print_callback, myFunc, myVoidPtr); */ yajl_gen_print_callback = 0x04, /** * Normally the generator does not validate that strings you * pass to it via yajl_gen_string() are valid UTF8. Enabling * this option will cause it to do so. */ yajl_gen_validate_utf8 = 0x08, /** * the forward solidus (slash or '/' in human) is not required to be * escaped in json text. By default, YAJL will not escape it in the * iterest of saving bytes. Setting this flag will cause YAJL to * always escape '/' in generated JSON strings. */ yajl_gen_escape_solidus = 0x10 } yajl_gen_option; /** allow the modification of generator options subsequent to handle * allocation (via yajl_alloc) * \returns zero in case of errors, non-zero otherwise */ YAJL_API int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...); /** allocate a generator handle * \param allocFuncs an optional pointer to a structure which allows * the client to overide the memory allocation * used by yajl. May be NULL, in which case * malloc/free/realloc will be used. * * \returns an allocated handle on success, NULL on failure (bad params) */ YAJL_API yajl_gen yajl_gen_alloc(const yajl_alloc_funcs * allocFuncs); /** free a generator handle */ YAJL_API void yajl_gen_free(yajl_gen handle); YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long long int number); /** generate a floating point number. number may not be infinity or * NaN, as these have no representation in JSON. In these cases the * generator will return 'yajl_gen_invalid_number' */ YAJL_API yajl_gen_status yajl_gen_double(yajl_gen hand, double number); YAJL_API yajl_gen_status yajl_gen_number(yajl_gen hand, const char * num, size_t len); YAJL_API yajl_gen_status yajl_gen_string(yajl_gen hand, const unsigned char * str, size_t len); YAJL_API yajl_gen_status yajl_gen_null(yajl_gen hand); YAJL_API yajl_gen_status yajl_gen_bool(yajl_gen hand, int boolean); YAJL_API yajl_gen_status yajl_gen_map_open(yajl_gen hand); YAJL_API yajl_gen_status yajl_gen_map_close(yajl_gen hand); YAJL_API yajl_gen_status yajl_gen_array_open(yajl_gen hand); YAJL_API yajl_gen_status yajl_gen_array_close(yajl_gen hand); /** access the null terminated generator buffer. If incrementally * outputing JSON, one should call yajl_gen_clear to clear the * buffer. This allows stream generation. */ YAJL_API yajl_gen_status yajl_gen_get_buf(yajl_gen hand, const unsigned char ** buf, size_t * len); /** clear yajl's output buffer, but maintain all internal generation * state. This function will not "reset" the generator state, and is * intended to enable incremental JSON outputing. */ YAJL_API void yajl_gen_clear(yajl_gen hand); #ifdef __cplusplus } #endif #endif lnav-0.7.0/src/yajl/api/yajl_parse.h000664 000765 000024 00000023143 12211635054 017533 0ustar00stackstaff000000 000000 /* * Copyright (c) 2007-2011, Lloyd Hilaiel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * \file yajl_parse.h * Interface to YAJL's JSON stream parsing facilities. */ #include #ifndef __YAJL_PARSE_H__ #define __YAJL_PARSE_H__ #include #ifdef __cplusplus extern "C" { #endif /** error codes returned from this interface */ typedef enum { /** no error was encountered */ yajl_status_ok, /** a client callback returned zero, stopping the parse */ yajl_status_client_canceled, /** An error occured during the parse. Call yajl_get_error for * more information about the encountered error */ yajl_status_error } yajl_status; /** attain a human readable, english, string for an error */ YAJL_API const char * yajl_status_to_string(yajl_status code); /** an opaque handle to a parser */ typedef struct yajl_handle_t * yajl_handle; /** yajl is an event driven parser. this means as json elements are * parsed, you are called back to do something with the data. The * functions in this table indicate the various events for which * you will be called back. Each callback accepts a "context" * pointer, this is a void * that is passed into the yajl_parse * function which the client code may use to pass around context. * * All callbacks return an integer. If non-zero, the parse will * continue. If zero, the parse will be canceled and * yajl_status_client_canceled will be returned from the parse. * * \attention { * A note about the handling of numbers: * * yajl will only convert numbers that can be represented in a * double or a 64 bit (long long) int. All other numbers will * be passed to the client in string form using the yajl_number * callback. Furthermore, if yajl_number is not NULL, it will * always be used to return numbers, that is yajl_integer and * yajl_double will be ignored. If yajl_number is NULL but one * of yajl_integer or yajl_double are defined, parsing of a * number larger than is representable in a double or 64 bit * integer will result in a parse error. * } */ typedef struct { int (* yajl_null)(void * ctx); int (* yajl_boolean)(void * ctx, int boolVal); int (* yajl_integer)(void * ctx, long long integerVal); int (* yajl_double)(void * ctx, double doubleVal); /** A callback which passes the string representation of the number * back to the client. Will be used for all numbers when present */ int (* yajl_number)(void * ctx, const char * numberVal, size_t numberLen); /** strings are returned as pointers into the JSON text when, * possible, as a result, they are _not_ null padded */ int (* yajl_string)(void * ctx, const unsigned char * stringVal, size_t stringLen); int (* yajl_start_map)(void * ctx); int (* yajl_map_key)(void * ctx, const unsigned char * key, size_t stringLen); int (* yajl_end_map)(void * ctx); int (* yajl_start_array)(void * ctx); int (* yajl_end_array)(void * ctx); } yajl_callbacks; /** allocate a parser handle * \param callbacks a yajl callbacks structure specifying the * functions to call when different JSON entities * are encountered in the input text. May be NULL, * which is only useful for validation. * \param afs memory allocation functions, may be NULL for to use * C runtime library routines (malloc and friends) * \param ctx a context pointer that will be passed to callbacks. */ YAJL_API yajl_handle yajl_alloc(const yajl_callbacks * callbacks, yajl_alloc_funcs * afs, void * ctx); /** configuration parameters for the parser, these may be passed to * yajl_config() along with option specific argument(s). In general, * all configuration parameters default to *off*. */ typedef enum { /** Ignore javascript style comments present in * JSON input. Non-standard, but rather fun * arguments: toggled off with integer zero, on otherwise. * * example: * yajl_config(h, yajl_allow_comments, 1); // turn comment support on */ yajl_allow_comments = 0x01, /** * When set the parser will verify that all strings in JSON input are * valid UTF8 and will emit a parse error if this is not so. When set, * this option makes parsing slightly more expensive (~7% depending * on processor and compiler in use) * * example: * yajl_config(h, yajl_dont_validate_strings, 1); // disable utf8 checking */ yajl_dont_validate_strings = 0x02, /** * By default, upon calls to yajl_complete_parse(), yajl will * ensure the entire input text was consumed and will raise an error * otherwise. Enabling this flag will cause yajl to disable this * check. This can be useful when parsing json out of a that contains more * than a single JSON document. */ yajl_allow_trailing_garbage = 0x04, /** * Allow multiple values to be parsed by a single handle. The * entire text must be valid JSON, and values can be seperated * by any kind of whitespace. This flag will change the * behavior of the parser, and cause it continue parsing after * a value is parsed, rather than transitioning into a * complete state. This option can be useful when parsing multiple * values from an input stream. */ yajl_allow_multiple_values = 0x08, /** * When yajl_complete_parse() is called the parser will * check that the top level value was completely consumed. I.E., * if called whilst in the middle of parsing a value * yajl will enter an error state (premature EOF). Setting this * flag suppresses that check and the corresponding error. */ yajl_allow_partial_values = 0x10 } yajl_option; /** allow the modification of parser options subsequent to handle * allocation (via yajl_alloc) * \returns zero in case of errors, non-zero otherwise */ YAJL_API int yajl_config(yajl_handle h, yajl_option opt, ...); /** free a parser handle */ YAJL_API void yajl_free(yajl_handle handle); /** Parse some json! * \param hand - a handle to the json parser allocated with yajl_alloc * \param jsonText - a pointer to the UTF8 json text to be parsed * \param jsonTextLength - the length, in bytes, of input text */ YAJL_API yajl_status yajl_parse(yajl_handle hand, const unsigned char * jsonText, size_t jsonTextLength); /** Parse any remaining buffered json. * Since yajl is a stream-based parser, without an explicit end of * input, yajl sometimes can't decide if content at the end of the * stream is valid or not. For example, if "1" has been fed in, * yajl can't know whether another digit is next or some character * that would terminate the integer token. * * \param hand - a handle to the json parser allocated with yajl_alloc */ YAJL_API yajl_status yajl_complete_parse(yajl_handle hand); /** get an error string describing the state of the * parse. * * If verbose is non-zero, the message will include the JSON * text where the error occured, along with an arrow pointing to * the specific char. * * \returns A dynamically allocated string will be returned which should * be freed with yajl_free_error */ YAJL_API unsigned char * yajl_get_error(yajl_handle hand, int verbose, const unsigned char * jsonText, size_t jsonTextLength); /** * get the amount of data consumed from the last chunk passed to YAJL. * * In the case of a successful parse this can help you understand if * the entire buffer was consumed (which will allow you to handle * "junk at end of input"). * * In the event an error is encountered during parsing, this function * affords the client a way to get the offset into the most recent * chunk where the error occured. 0 will be returned if no error * was encountered. */ YAJL_API size_t yajl_get_bytes_consumed(yajl_handle hand); /** free an error returned from yajl_get_error */ YAJL_API void yajl_free_error(yajl_handle hand, unsigned char * str); #ifdef __cplusplus } #endif #endif lnav-0.7.0/src/yajl/api/yajl_tree.h000664 000765 000024 00000015660 12211635054 017365 0ustar00stackstaff000000 000000 /* * Copyright (c) 2010-2011 Florian Forster * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /** * \file yajl_tree.h * * Parses JSON data and returns the data in tree form. * * \author Florian Forster * \date August 2010 * * This interface makes quick parsing and extraction of * smallish JSON docs trivial: * * \include example/parse_config.c */ #ifndef YAJL_TREE_H #define YAJL_TREE_H 1 #include /** possible data types that a yajl_val_s can hold */ typedef enum { yajl_t_string = 1, yajl_t_number = 2, yajl_t_object = 3, yajl_t_array = 4, yajl_t_true = 5, yajl_t_false = 6, yajl_t_null = 7, /** The any type isn't valid for yajl_val_s.type, but can be * used as an argument to routines like yajl_tree_get(). */ yajl_t_any = 8 } yajl_type; #define YAJL_NUMBER_INT_VALID 0x01 #define YAJL_NUMBER_DOUBLE_VALID 0x02 /** A pointer to a node in the parse tree */ typedef struct yajl_val_s * yajl_val; /** * A JSON value representation capable of holding one of the seven * types above. For "string", "number", "object", and "array" * additional data is available in the union. The "YAJL_IS_*" * and "YAJL_GET_*" macros below allow type checking and convenient * value extraction. */ struct yajl_val_s { /** Type of the value contained. Use the "YAJL_IS_*" macors to check for a * specific type. */ yajl_type type; /** Type-specific data. You may use the "YAJL_GET_*" macros to access these * members. */ union { char * string; struct { long long i; /*< integer value, if representable. */ double d; /*< double value, if representable. */ /** Signals whether the \em i and \em d members are * valid. See \c YAJL_NUMBER_INT_VALID and * \c YAJL_NUMBER_DOUBLE_VALID. */ char *r; /*< unparsed number in string form. */ unsigned int flags; } number; struct { const char **keys; /*< Array of keys */ yajl_val *values; /*< Array of values. */ size_t len; /*< Number of key-value-pairs. */ } object; struct { yajl_val *values; /*< Array of elements. */ size_t len; /*< Number of elements. */ } array; } u; }; /** * Parse a string. * * Parses an null-terminated string containing JSON data and returns a pointer * to the top-level value (root of the parse tree). * * \param input Pointer to a null-terminated utf8 string containing * JSON data. * \param error_buffer Pointer to a buffer in which an error message will * be stored if \em yajl_tree_parse fails, or * \c NULL. The buffer will be initialized before * parsing, so its content will be destroyed even if * \em yajl_tree_parse succeeds. * \param error_buffer_size Size of the memory area pointed to by * \em error_buffer_size. If \em error_buffer_size is * \c NULL, this argument is ignored. * * \returns Pointer to the top-level value or \c NULL on error. The memory * pointed to must be freed using \em yajl_tree_free. In case of an error, a * null terminated message describing the error in more detail is stored in * \em error_buffer if it is not \c NULL. */ YAJL_API yajl_val yajl_tree_parse (const char *input, char *error_buffer, size_t error_buffer_size); /** * Free a parse tree returned by "yajl_tree_parse". * * \param v Pointer to a JSON value returned by "yajl_tree_parse". Passing NULL * is valid and results in a no-op. */ YAJL_API void yajl_tree_free (yajl_val v); /** * Access a nested value inside a tree. * * \param parent the node under which you'd like to extract values. * \param path A null terminated array of strings, each the name of an object key * \param type the yajl_type of the object you seek, or yajl_t_any if any will do. * * \returns a pointer to the found value, or NULL if we came up empty. * * Future Ideas: it'd be nice to move path to a string and implement support for * a teeny tiny micro language here, so you can extract array elements, do things * like .first and .last, even .length. Inspiration from JSONPath and css selectors? * No it wouldn't be fast, but that's not what this API is about. */ YAJL_API yajl_val yajl_tree_get(yajl_val parent, const char ** path, yajl_type type); /* Various convenience macros to check the type of a `yajl_val` */ #define YAJL_IS_STRING(v) (((v) != NULL) && ((v)->type == yajl_t_string)) #define YAJL_IS_NUMBER(v) (((v) != NULL) && ((v)->type == yajl_t_number)) #define YAJL_IS_INTEGER(v) (YAJL_IS_NUMBER(v) && ((v)->u.flags & YAJL_NUMBER_INT_VALID)) #define YAJL_IS_DOUBLE(v) (YAJL_IS_NUMBER(v) && ((v)->u.flags & YAJL_NUMBER_DOUBLE_VALID)) #define YAJL_IS_OBJECT(v) (((v) != NULL) && ((v)->type == yajl_t_object)) #define YAJL_IS_ARRAY(v) (((v) != NULL) && ((v)->type == yajl_t_array )) #define YAJL_IS_TRUE(v) (((v) != NULL) && ((v)->type == yajl_t_true )) #define YAJL_IS_FALSE(v) (((v) != NULL) && ((v)->type == yajl_t_false )) #define YAJL_IS_NULL(v) (((v) != NULL) && ((v)->type == yajl_t_null )) /** Given a yajl_val_string return a ptr to the bare string it contains, * or NULL if the value is not a string. */ #define YAJL_GET_STRING(v) (YAJL_IS_STRING(v) ? (v)->u.string : NULL) /** Get the string representation of a number. You should check type first, * perhaps using YAJL_IS_NUMBER */ #define YAJL_GET_NUMBER(v) ((v)->u.number.r) /** Get the double representation of a number. You should check type first, * perhaps using YAJL_IS_DOUBLE */ #define YAJL_GET_DOUBLE(v) ((v)->u.number.d) /** Get the 64bit (long long) integer representation of a number. You should * check type first, perhaps using YAJL_IS_INTEGER */ #define YAJL_GET_INTEGER(v) ((v)->u.number.i) /** Get a pointer to a yajl_val_object or NULL if the value is not an object. */ #define YAJL_GET_OBJECT(v) (YAJL_IS_OBJECT(v) ? &(v)->u.object : NULL) /** Get a pointer to a yajl_val_array or NULL if the value is not an object. */ #define YAJL_GET_ARRAY(v) (YAJL_IS_ARRAY(v) ? &(v)->u.array : NULL) #endif /* YAJL_TREE_H */ lnav-0.7.0/src/spookyhash/SpookyV2.cpp000664 000765 000024 00000020521 12274203105 020103 0ustar00stackstaff000000 000000 // Spooky Hash // A 128-bit noncryptographic hash, for checksums and table lookup // By Bob Jenkins. Public domain. // Oct 31 2010: published framework, disclaimer ShortHash isn't right // Nov 7 2010: disabled ShortHash // Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again // April 10 2012: buffer overflow on platforms without unaligned reads // July 12 2012: was passing out variables in final to in/out in short // July 30 2012: I reintroduced the buffer overflow // August 5 2012: SpookyV2: d = should be d += in short hash, and remove extra mix from long hash #include #include "SpookyV2.h" #define ALLOW_UNALIGNED_READS 1 // // short hash ... it could be used on any message, // but it's used by Spooky just for short messages. // void SpookyHash::Short( const void *message, size_t length, uint64 *hash1, uint64 *hash2) { uint64 buf[2*sc_numVars]; union { const uint8 *p8; uint32 *p32; uint64 *p64; size_t i; } u; u.p8 = (const uint8 *)message; if (!ALLOW_UNALIGNED_READS && (u.i & 0x7)) { memcpy(buf, message, length); u.p64 = buf; } size_t remainder = length%32; uint64 a=*hash1; uint64 b=*hash2; uint64 c=sc_const; uint64 d=sc_const; if (length > 15) { const uint64 *end = u.p64 + (length/32)*4; // handle all complete sets of 32 bytes for (; u.p64 < end; u.p64 += 4) { c += u.p64[0]; d += u.p64[1]; ShortMix(a,b,c,d); a += u.p64[2]; b += u.p64[3]; } //Handle the case of 16+ remaining bytes. if (remainder >= 16) { c += u.p64[0]; d += u.p64[1]; ShortMix(a,b,c,d); u.p64 += 2; remainder -= 16; } } // Handle the last 0..15 bytes, and its length d += ((uint64)length) << 56; switch (remainder) { case 15: d += ((uint64)u.p8[14]) << 48; case 14: d += ((uint64)u.p8[13]) << 40; case 13: d += ((uint64)u.p8[12]) << 32; case 12: d += u.p32[2]; c += u.p64[0]; break; case 11: d += ((uint64)u.p8[10]) << 16; case 10: d += ((uint64)u.p8[9]) << 8; case 9: d += (uint64)u.p8[8]; case 8: c += u.p64[0]; break; case 7: c += ((uint64)u.p8[6]) << 48; case 6: c += ((uint64)u.p8[5]) << 40; case 5: c += ((uint64)u.p8[4]) << 32; case 4: c += u.p32[0]; break; case 3: c += ((uint64)u.p8[2]) << 16; case 2: c += ((uint64)u.p8[1]) << 8; case 1: c += (uint64)u.p8[0]; break; case 0: c += sc_const; d += sc_const; } ShortEnd(a,b,c,d); *hash1 = a; *hash2 = b; } // do the whole hash in one call void SpookyHash::Hash128( const void *message, size_t length, uint64 *hash1, uint64 *hash2) { if (length < sc_bufSize) { Short(message, length, hash1, hash2); return; } uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11; uint64 buf[sc_numVars]; uint64 *end; union { const uint8 *p8; uint64 *p64; size_t i; } u; size_t remainder; h0=h3=h6=h9 = *hash1; h1=h4=h7=h10 = *hash2; h2=h5=h8=h11 = sc_const; u.p8 = (const uint8 *)message; end = u.p64 + (length/sc_blockSize)*sc_numVars; // handle all whole sc_blockSize blocks of bytes if (ALLOW_UNALIGNED_READS || ((u.i & 0x7) == 0)) { while (u.p64 < end) { Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); u.p64 += sc_numVars; } } else { while (u.p64 < end) { memcpy(buf, u.p64, sc_blockSize); Mix(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); u.p64 += sc_numVars; } } // handle the last partial block of sc_blockSize bytes remainder = (length - ((const uint8 *)end-(const uint8 *)message)); memcpy(buf, end, remainder); memset(((uint8 *)buf)+remainder, 0, sc_blockSize-remainder); ((uint8 *)buf)[sc_blockSize-1] = remainder; // do some final mixing End(buf, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); *hash1 = h0; *hash2 = h1; } // init spooky state void SpookyHash::Init(uint64 seed1, uint64 seed2) { m_length = 0; m_remainder = 0; m_state[0] = seed1; m_state[1] = seed2; } // add a message fragment to the state void SpookyHash::Update(const void *message, size_t length) { uint64 h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11; size_t newLength = length + m_remainder; uint8 remainder; union { const uint8 *p8; uint64 *p64; size_t i; } u; const uint64 *end; // Is this message fragment too short? If it is, stuff it away. if (newLength < sc_bufSize) { memcpy(&((uint8 *)m_data)[m_remainder], message, length); m_length = length + m_length; m_remainder = (uint8)newLength; return; } // init the variables if (m_length < sc_bufSize) { h0=h3=h6=h9 = m_state[0]; h1=h4=h7=h10 = m_state[1]; h2=h5=h8=h11 = sc_const; } else { h0 = m_state[0]; h1 = m_state[1]; h2 = m_state[2]; h3 = m_state[3]; h4 = m_state[4]; h5 = m_state[5]; h6 = m_state[6]; h7 = m_state[7]; h8 = m_state[8]; h9 = m_state[9]; h10 = m_state[10]; h11 = m_state[11]; } m_length = length + m_length; // if we've got anything stuffed away, use it now if (m_remainder) { uint8 prefix = sc_bufSize-m_remainder; memcpy(&(((uint8 *)m_data)[m_remainder]), message, prefix); u.p64 = m_data; Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); Mix(&u.p64[sc_numVars], h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); u.p8 = ((const uint8 *)message) + prefix; length -= prefix; } else { u.p8 = (const uint8 *)message; } // handle all whole blocks of sc_blockSize bytes end = u.p64 + (length/sc_blockSize)*sc_numVars; remainder = (uint8)(length-((const uint8 *)end-u.p8)); if (ALLOW_UNALIGNED_READS || (u.i & 0x7) == 0) { while (u.p64 < end) { Mix(u.p64, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); u.p64 += sc_numVars; } } else { while (u.p64 < end) { memcpy(m_data, u.p8, sc_blockSize); Mix(m_data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); u.p64 += sc_numVars; } } // stuff away the last few bytes m_remainder = remainder; memcpy(m_data, end, remainder); // stuff away the variables m_state[0] = h0; m_state[1] = h1; m_state[2] = h2; m_state[3] = h3; m_state[4] = h4; m_state[5] = h5; m_state[6] = h6; m_state[7] = h7; m_state[8] = h8; m_state[9] = h9; m_state[10] = h10; m_state[11] = h11; } // report the hash for the concatenation of all message fragments so far void SpookyHash::Final(uint64 *hash1, uint64 *hash2) { // init the variables if (m_length < sc_bufSize) { *hash1 = m_state[0]; *hash2 = m_state[1]; Short( m_data, m_length, hash1, hash2); return; } const uint64 *data = (const uint64 *)m_data; uint8 remainder = m_remainder; uint64 h0 = m_state[0]; uint64 h1 = m_state[1]; uint64 h2 = m_state[2]; uint64 h3 = m_state[3]; uint64 h4 = m_state[4]; uint64 h5 = m_state[5]; uint64 h6 = m_state[6]; uint64 h7 = m_state[7]; uint64 h8 = m_state[8]; uint64 h9 = m_state[9]; uint64 h10 = m_state[10]; uint64 h11 = m_state[11]; if (remainder >= sc_blockSize) { // m_data can contain two blocks; handle any whole first block Mix(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); data += sc_numVars; remainder -= sc_blockSize; } // mix in the last partial block, and the length mod sc_blockSize memset(&((uint8 *)data)[remainder], 0, (sc_blockSize-remainder)); ((uint8 *)data)[sc_blockSize-1] = remainder; // do some final mixing End(data, h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); *hash1 = h0; *hash2 = h1; } lnav-0.7.0/src/spookyhash/SpookyV2.h000664 000765 000024 00000027255 12274203105 017563 0ustar00stackstaff000000 000000 // // SpookyHash: a 128-bit noncryptographic hash function // By Bob Jenkins, public domain // Oct 31 2010: alpha, framework + SpookyHash::Mix appears right // Oct 31 2011: alpha again, Mix only good to 2^^69 but rest appears right // Dec 31 2011: beta, improved Mix, tested it for 2-bit deltas // Feb 2 2012: production, same bits as beta // Feb 5 2012: adjusted definitions of uint* to be more portable // Mar 30 2012: 3 bytes/cycle, not 4. Alpha was 4 but wasn't thorough enough. // August 5 2012: SpookyV2 (different results) // // Up to 3 bytes/cycle for long messages. Reasonably fast for short messages. // All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit. // // This was developed for and tested on 64-bit x86-compatible processors. // It assumes the processor is little-endian. There is a macro // controlling whether unaligned reads are allowed (by default they are). // This should be an equally good hash on big-endian machines, but it will // compute different results on them than on little-endian machines. // // Google's CityHash has similar specs to SpookyHash, and CityHash is faster // on new Intel boxes. MD4 and MD5 also have similar specs, but they are orders // of magnitude slower. CRCs are two or more times slower, but unlike // SpookyHash, they have nice math for combining the CRCs of pieces to form // the CRCs of wholes. There are also cryptographic hashes, but those are even // slower than MD5. // #ifndef _SPOOKYHASH_V2_H #define _SPOOKYHASH_V2_H #include #ifdef _MSC_VER # define INLINE __forceinline typedef unsigned __int64 uint64; typedef unsigned __int32 uint32; typedef unsigned __int16 uint16; typedef unsigned __int8 uint8; #else # include # define INLINE inline typedef uint64_t uint64; typedef uint32_t uint32; typedef uint16_t uint16; typedef uint8_t uint8; #endif class SpookyHash { public: // // SpookyHash: hash a single message in one call, produce 128-bit output // static void Hash128( const void *message, // message to hash size_t length, // length of message in bytes uint64 *hash1, // in/out: in seed 1, out hash value 1 uint64 *hash2); // in/out: in seed 2, out hash value 2 // // Hash64: hash a single message in one call, return 64-bit output // static uint64 Hash64( const void *message, // message to hash size_t length, // length of message in bytes uint64 seed) // seed { uint64 hash1 = seed; Hash128(message, length, &hash1, &seed); return hash1; } // // Hash32: hash a single message in one call, produce 32-bit output // static uint32 Hash32( const void *message, // message to hash size_t length, // length of message in bytes uint32 seed) // seed { uint64 hash1 = seed, hash2 = seed; Hash128(message, length, &hash1, &hash2); return (uint32)hash1; } // // Init: initialize the context of a SpookyHash // void Init( uint64 seed1, // any 64-bit value will do, including 0 uint64 seed2); // different seeds produce independent hashes // // Update: add a piece of a message to a SpookyHash state // void Update( const void *message, // message fragment size_t length); // length of message fragment in bytes // // Final: compute the hash for the current SpookyHash state // // This does not modify the state; you can keep updating it afterward // // The result is the same as if SpookyHash() had been called with // all the pieces concatenated into one message. // void Final( uint64 *hash1, // out only: first 64 bits of hash value. uint64 *hash2); // out only: second 64 bits of hash value. // // left rotate a 64-bit value by k bytes // static INLINE uint64 Rot64(uint64 x, int k) { return (x << k) | (x >> (64 - k)); } // // This is used if the input is 96 bytes long or longer. // // The internal state is fully overwritten every 96 bytes. // Every input bit appears to cause at least 128 bits of entropy // before 96 other bytes are combined, when run forward or backward // For every input bit, // Two inputs differing in just that input bit // Where "differ" means xor or subtraction // And the base value is random // When run forward or backwards one Mix // I tried 3 pairs of each; they all differed by at least 212 bits. // static INLINE void Mix( const uint64 *data, uint64 &s0, uint64 &s1, uint64 &s2, uint64 &s3, uint64 &s4, uint64 &s5, uint64 &s6, uint64 &s7, uint64 &s8, uint64 &s9, uint64 &s10,uint64 &s11) { s0 += data[0]; s2 ^= s10; s11 ^= s0; s0 = Rot64(s0,11); s11 += s1; s1 += data[1]; s3 ^= s11; s0 ^= s1; s1 = Rot64(s1,32); s0 += s2; s2 += data[2]; s4 ^= s0; s1 ^= s2; s2 = Rot64(s2,43); s1 += s3; s3 += data[3]; s5 ^= s1; s2 ^= s3; s3 = Rot64(s3,31); s2 += s4; s4 += data[4]; s6 ^= s2; s3 ^= s4; s4 = Rot64(s4,17); s3 += s5; s5 += data[5]; s7 ^= s3; s4 ^= s5; s5 = Rot64(s5,28); s4 += s6; s6 += data[6]; s8 ^= s4; s5 ^= s6; s6 = Rot64(s6,39); s5 += s7; s7 += data[7]; s9 ^= s5; s6 ^= s7; s7 = Rot64(s7,57); s6 += s8; s8 += data[8]; s10 ^= s6; s7 ^= s8; s8 = Rot64(s8,55); s7 += s9; s9 += data[9]; s11 ^= s7; s8 ^= s9; s9 = Rot64(s9,54); s8 += s10; s10 += data[10]; s0 ^= s8; s9 ^= s10; s10 = Rot64(s10,22); s9 += s11; s11 += data[11]; s1 ^= s9; s10 ^= s11; s11 = Rot64(s11,46); s10 += s0; } // // Mix all 12 inputs together so that h0, h1 are a hash of them all. // // For two inputs differing in just the input bits // Where "differ" means xor or subtraction // And the base value is random, or a counting value starting at that bit // The final result will have each bit of h0, h1 flip // For every input bit, // with probability 50 +- .3% // For every pair of input bits, // with probability 50 +- 3% // // This does not rely on the last Mix() call having already mixed some. // Two iterations was almost good enough for a 64-bit result, but a // 128-bit result is reported, so End() does three iterations. // static INLINE void EndPartial( uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3, uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7, uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11) { h11+= h1; h2 ^= h11; h1 = Rot64(h1,44); h0 += h2; h3 ^= h0; h2 = Rot64(h2,15); h1 += h3; h4 ^= h1; h3 = Rot64(h3,34); h2 += h4; h5 ^= h2; h4 = Rot64(h4,21); h3 += h5; h6 ^= h3; h5 = Rot64(h5,38); h4 += h6; h7 ^= h4; h6 = Rot64(h6,33); h5 += h7; h8 ^= h5; h7 = Rot64(h7,10); h6 += h8; h9 ^= h6; h8 = Rot64(h8,13); h7 += h9; h10^= h7; h9 = Rot64(h9,38); h8 += h10; h11^= h8; h10= Rot64(h10,53); h9 += h11; h0 ^= h9; h11= Rot64(h11,42); h10+= h0; h1 ^= h10; h0 = Rot64(h0,54); } static INLINE void End( const uint64 *data, uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3, uint64 &h4, uint64 &h5, uint64 &h6, uint64 &h7, uint64 &h8, uint64 &h9, uint64 &h10,uint64 &h11) { h0 += data[0]; h1 += data[1]; h2 += data[2]; h3 += data[3]; h4 += data[4]; h5 += data[5]; h6 += data[6]; h7 += data[7]; h8 += data[8]; h9 += data[9]; h10 += data[10]; h11 += data[11]; EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); EndPartial(h0,h1,h2,h3,h4,h5,h6,h7,h8,h9,h10,h11); } // // The goal is for each bit of the input to expand into 128 bits of // apparent entropy before it is fully overwritten. // n trials both set and cleared at least m bits of h0 h1 h2 h3 // n: 2 m: 29 // n: 3 m: 46 // n: 4 m: 57 // n: 5 m: 107 // n: 6 m: 146 // n: 7 m: 152 // when run forwards or backwards // for all 1-bit and 2-bit diffs // with diffs defined by either xor or subtraction // with a base of all zeros plus a counter, or plus another bit, or random // static INLINE void ShortMix(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3) { h2 = Rot64(h2,50); h2 += h3; h0 ^= h2; h3 = Rot64(h3,52); h3 += h0; h1 ^= h3; h0 = Rot64(h0,30); h0 += h1; h2 ^= h0; h1 = Rot64(h1,41); h1 += h2; h3 ^= h1; h2 = Rot64(h2,54); h2 += h3; h0 ^= h2; h3 = Rot64(h3,48); h3 += h0; h1 ^= h3; h0 = Rot64(h0,38); h0 += h1; h2 ^= h0; h1 = Rot64(h1,37); h1 += h2; h3 ^= h1; h2 = Rot64(h2,62); h2 += h3; h0 ^= h2; h3 = Rot64(h3,34); h3 += h0; h1 ^= h3; h0 = Rot64(h0,5); h0 += h1; h2 ^= h0; h1 = Rot64(h1,36); h1 += h2; h3 ^= h1; } // // Mix all 4 inputs together so that h0, h1 are a hash of them all. // // For two inputs differing in just the input bits // Where "differ" means xor or subtraction // And the base value is random, or a counting value starting at that bit // The final result will have each bit of h0, h1 flip // For every input bit, // with probability 50 +- .3% (it is probably better than that) // For every pair of input bits, // with probability 50 +- .75% (the worst case is approximately that) // static INLINE void ShortEnd(uint64 &h0, uint64 &h1, uint64 &h2, uint64 &h3) { h3 ^= h2; h2 = Rot64(h2,15); h3 += h2; h0 ^= h3; h3 = Rot64(h3,52); h0 += h3; h1 ^= h0; h0 = Rot64(h0,26); h1 += h0; h2 ^= h1; h1 = Rot64(h1,51); h2 += h1; h3 ^= h2; h2 = Rot64(h2,28); h3 += h2; h0 ^= h3; h3 = Rot64(h3,9); h0 += h3; h1 ^= h0; h0 = Rot64(h0,47); h1 += h0; h2 ^= h1; h1 = Rot64(h1,54); h2 += h1; h3 ^= h2; h2 = Rot64(h2,32); h3 += h2; h0 ^= h3; h3 = Rot64(h3,25); h0 += h3; h1 ^= h0; h0 = Rot64(h0,63); h1 += h0; } private: // // Short is used for messages under 192 bytes in length // Short has a low startup cost, the normal mode is good for long // keys, the cost crossover is at about 192 bytes. The two modes were // held to the same quality bar. // static void Short( const void *message, // message (array of bytes, not necessarily aligned) size_t length, // length of message (in bytes) uint64 *hash1, // in/out: in the seed, out the hash value uint64 *hash2); // in/out: in the seed, out the hash value // number of uint64's in internal state static const size_t sc_numVars = 12; // size of the internal state static const size_t sc_blockSize = sc_numVars*8; // size of buffer of unhashed data, in bytes static const size_t sc_bufSize = 2*sc_blockSize; // // sc_const: a constant which: // * is not zero // * is odd // * is a not-very-regular mix of 1's and 0's // * does not need any other special mathematical properties // static const uint64 sc_const = 0xdeadbeefdeadbeefLL; uint64 m_data[2*sc_numVars]; // unhashed data, for partial messages uint64 m_state[sc_numVars]; // internal state of the hash size_t m_length; // total length of the input so far uint8 m_remainder; // length of unhashed data stashed in m_data }; #endif