Target a minimal terminfo library rather than necessarily a full curses
authorChandler Carruth <chandlerc@gmail.com>
Mon, 12 Aug 2013 09:49:17 +0000 (09:49 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Mon, 12 Aug 2013 09:49:17 +0000 (09:49 +0000)
library for color support detection. This still will use a curses
library if that is all we have available on the system. This change
tries to use a smaller subset of the curses library, specifically the
subset that is on some systems split off into a separate library. For
example, if you install ncurses configured --with-tinfo, a 'libtinfo' is
install that provides just the terminfo querying functionality. That
library is now used instead of curses when it is available.

This happens to fix a build error on systems with that library because
when we tried to link ncurses into the binary, we didn't pull tinfo in
as well. =]

It should also provide an easy path for supporting the NetBSD
libterminfo library, but as I don't have access to a NetBSD system I'm
leaving adding that support to those folks.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188160 91177308-0d34-0410-b5e6-96231b3b80d8

CMakeLists.txt
autoconf/configure.ac
cmake/config-ix.cmake
cmake/modules/LLVM-Config.cmake
cmake/modules/LLVMConfig.cmake.in
configure
include/llvm/Config/config.h.cmake
include/llvm/Config/config.h.in
lib/Support/Unix/Process.inc

index a0a6c75..3bd9e11 100644 (file)
@@ -123,7 +123,7 @@ set(FFI_INCLUDE_DIR "" CACHE PATH "Additional directory, where CMake should sear
 set(LLVM_TARGET_ARCH "host"
   CACHE STRING "Set target to use for LLVM JIT or use \"host\" for automatic detection.")
 
-option(LLVM_ENABLE_CURSES "Use curses to detect terminal info if available." ON)
+option(LLVM_ENABLE_TERMINFO "Use terminfo database if available." ON)
 
 option(LLVM_ENABLE_THREADS "Use threads if available." ON)
 
index 30481ea..127eb6f 100644 (file)
@@ -1072,16 +1072,16 @@ AC_ARG_WITH(bug-report-url,
 AC_DEFINE_UNQUOTED(BUG_REPORT_URL,"$withval",
                    [Bug report URL.])
 
-dnl --enable-curses: check whether the user wants to control use of curses:
-AC_ARG_ENABLE(curses,AS_HELP_STRING(
-  [--enable-curses],
-  [Use curses for querying terminal infomation if available (default is YES)]),
+dnl --enable-terminfo: check whether the user wants to control use of terminfo:
+AC_ARG_ENABLE(terminfo,AS_HELP_STRING(
+  [--enable-terminfo],
+  [Query the terminfo database if available (default is YES)]),
   [case "$enableval" in
-    yes) llvm_cv_enable_curses="yes" ;;
-    no)  llvm_cv_enable_curses="no"  ;;
-    *) AC_MSG_ERROR([Invalid setting for --enable-curses. Use "yes" or "no"]) ;;
+    yes) llvm_cv_enable_terminfo="yes" ;;
+    no)  llvm_cv_enable_terminfo="no"  ;;
+    *) AC_MSG_ERROR([Invalid setting for --enable-terminfo. Use "yes" or "no"]) ;;
   esac],
-  llvm_cv_enable_curses="yes")
+  llvm_cv_enable_terminfo="yes")
 
 dnl --enable-libffi : check whether the user wants to turn off libffi:
 AC_ARG_ENABLE(libffi,AS_HELP_STRING(
@@ -1390,11 +1390,11 @@ dnl right libraries to link with.
 AC_SEARCH_LIBS(clock_gettime,rt)
 
 dnl The curses library is optional; used for querying terminal info
-if test "$llvm_cv_enable_curses" = "yes" ; then
+if test "$llvm_cv_enable_terminfo" = "yes" ; then
   dnl We need the has_color functionality in curses for it to be useful.
-  AC_SEARCH_LIBS(has_colors,curses ncurses ncursesw,
-                 AC_DEFINE([HAVE_CURSES],[1],
-                           [Define if curses provides the has_color() function on this platform.]))
+  AC_SEARCH_LIBS(setupterm,tinfo curses ncurses ncursesw,
+                 AC_DEFINE([HAVE_TERMINFO],[1],
+                           [Define if the setupterm() function is supported this platform.]))
 fi
 
 dnl libffi is optional; used to call external functions from the interpreter
@@ -1574,8 +1574,8 @@ else
 fi
 
 dnl Try to find a suitable curses header.
-if test "$llvm_cv_enable_curses" = "yes" ; then
-  AC_CHECK_HEADERS([curses.h ncurses.h ncursesw.h ncurses/curses.h ncursesw/curses.h])
+if test "$llvm_cv_enable_terminfo" = "yes" ; then
+  AC_CHECK_HEADERS([term.h curses.h ncurses.h ncursesw.h ncurses/curses.h ncursesw/curses.h])
 fi
 
 dnl Try to find ffi.h.
index 0567820..13bd40d 100755 (executable)
@@ -74,6 +74,7 @@ check_symbol_exists(FE_INEXACT "fenv.h" HAVE_DECL_FE_INEXACT)
 check_include_file(mach/mach.h HAVE_MACH_MACH_H)
 check_include_file(mach-o/dyld.h HAVE_MACH_O_DYLD_H)
 
+check_include_file(term.h HAVE_TERM_H)
 check_include_file(curses.h HAVE_CURSES_H)
 check_include_file(ncurses.h HAVE_NCURSES_H)
 check_include_file(ncursesw.h HAVE_NCURSESW_H)
@@ -103,18 +104,21 @@ if( NOT PURE_WINDOWS )
   else()
     set(HAVE_LIBZ 0)
   endif()
-  if(LLVM_ENABLE_CURSES)
-    check_library_exists(curses has_colors "" HAVE_CURSES)
-    if(NOT HAVE_CURSES)
-      check_library_exists(ncurses has_colors "" HAVE_NCURSES)
-      set(HAVE_CURSES ${HAVE_NCURSES})
-      if(NOT HAVE_CURSES)
-        check_library_exists(ncursesw has_colors "" HAVE_NCURSESW)
-        set(HAVE_CURSES ${HAVE_NCURSESW})
+  if(LLVM_ENABLE_TERMINFO AND
+     (HAVE_TERM_H OR HAVE_CURSES_H OR HAVE_NCURSES_H OR HAVE_NCURSESW_H OR
+      HAVE_NCURSES_CURSES_H OR HAVE_NCURSESW_CURSES_H))
+    set(HAVE_TERMINFO 0)
+    foreach(library tinfo curses ncurses ncursesw)
+      string(TOUPPER ${library} library_suffix)
+      check_library_exists(${library} setupterm "" HAVE_TERMINFO_${library_suffix})
+      if(HAVE_TERMINFO_${library_suffix})
+        set(HAVE_TERMINFO 1)
+        set(TERMINFO_LIBS "${library}")
+        break()
       endif()
-    endif()
+    endforeach()
   else()
-    set(HAVE_CURSES 0)
+    set(HAVE_TERMINFO 0)
   endif()
 endif()
 
index 3e2447a..9fa45ce 100644 (file)
@@ -10,13 +10,9 @@ function(get_system_libs return_var)
       if( HAVE_LIBDL )
         set(system_libs ${system_libs} ${CMAKE_DL_LIBS})
       endif()
-      if(LLVM_ENABLE_CURSES)
-        if(HAVE_NCURSESW)
-          set(system_libs ${system_libs} ncursesw)
-        elseif(HAVE_NCURSES)
-          set(system_libs ${system_libs} ncurses)
-        elseif(HAVE_CURSES)
-          set(system_libs ${system_libs} curses)
+      if(LLVM_ENABLE_TERMINFO)
+        if(HAVE_TERMINFO)
+          set(system_libs ${system_libs} ${TERMINFO_LIBS})
         endif()
       endif()
       if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD )
index d87e242..68fe296 100644 (file)
@@ -20,7 +20,7 @@ set(TARGET_TRIPLE "@TARGET_TRIPLE@")
 
 set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@)
 
-set(LLVM_ENABLE_CURSES @LLVM_ENABLE_CURSES@)
+set(LLVM_ENABLE_TERMINFO @LLVM_ENABLE_TERMINFO@)
 
 set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS@)
 
@@ -30,9 +30,8 @@ set(LLVM_NATIVE_ARCH @LLVM_NATIVE_ARCH@)
 
 set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@)
 
-set(HAVE_CURSES @HAVE_CURSES@)
-set(HAVE_NCURSES @HAVE_NCURSES@)
-set(HAVE_NCURSESW @HAVE_NCURSESW@)
+set(HAVE_TERMINFO @HAVE_TERMINFO@)
+set(TERMINFO_LIBS @TERMINFO_LIBS@)
 set(HAVE_LIBDL @HAVE_LIBDL@)
 set(HAVE_LIBPTHREAD @HAVE_LIBPTHREAD@)
 set(HAVE_LIBZ @HAVE_LIBZ@)
index a148711..2bf6248 100755 (executable)
--- a/configure
+++ b/configure
@@ -1453,8 +1453,8 @@ Optional Features:
                           target1,target2,... (default=disable)
   --enable-bindings       Build specific language bindings:
                           all,auto,none,{binding-name} (default=auto)
-  --enable-curses         Use curses for querying terminal infomation if
-                          available (default is YES)
+  --enable-terminfo       Query the terminfo database if available (default is
+                          YES)
   --enable-libffi         Check for the presence of libffi (default is NO)
   --enable-ltdl-install   install libltdl
 
@@ -6006,17 +6006,17 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
-# Check whether --enable-curses was given.
-if test "${enable_curses+set}" = set; then
-  enableval=$enable_curses; case "$enableval" in
-    yes) llvm_cv_enable_curses="yes" ;;
-    no)  llvm_cv_enable_curses="no"  ;;
-    *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-curses. Use \"yes\" or \"no\"" >&5
-echo "$as_me: error: Invalid setting for --enable-curses. Use \"yes\" or \"no\"" >&2;}
+# Check whether --enable-terminfo was given.
+if test "${enable_terminfo+set}" = set; then
+  enableval=$enable_terminfo; case "$enableval" in
+    yes) llvm_cv_enable_terminfo="yes" ;;
+    no)  llvm_cv_enable_terminfo="no"  ;;
+    *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-terminfo. Use \"yes\" or \"no\"" >&5
+echo "$as_me: error: Invalid setting for --enable-terminfo. Use \"yes\" or \"no\"" >&2;}
    { (exit 1); exit 1; }; } ;;
   esac
 else
-  llvm_cv_enable_curses="yes"
+  llvm_cv_enable_terminfo="yes"
 fi
 
 
@@ -12268,10 +12268,10 @@ if test "$ac_res" != no; then
 fi
 
 
-if test "$llvm_cv_enable_curses" = "yes" ; then
-    { echo "$as_me:$LINENO: checking for library containing has_colors" >&5
-echo $ECHO_N "checking for library containing has_colors... $ECHO_C" >&6; }
-if test "${ac_cv_search_has_colors+set}" = set; then
+if test "$llvm_cv_enable_terminfo" = "yes" ; then
+    { echo "$as_me:$LINENO: checking for library containing setupterm" >&5
+echo $ECHO_N "checking for library containing setupterm... $ECHO_C" >&6; }
+if test "${ac_cv_search_setupterm+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_func_search_save_LIBS=$LIBS
@@ -12288,16 +12288,16 @@ cat >>conftest.$ac_ext <<_ACEOF
 #ifdef __cplusplus
 extern "C"
 #endif
-char has_colors ();
+char setupterm ();
 int
 main ()
 {
-return has_colors ();
+return setupterm ();
   ;
   return 0;
 }
 _ACEOF
-for ac_lib in '' curses ncurses ncursesw; do
+for ac_lib in '' tinfo curses ncurses ncursesw; do
   if test -z "$ac_lib"; then
     ac_res="none required"
   else
@@ -12338,7 +12338,7 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
   ac_status=$?
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); }; }; then
-  ac_cv_search_has_colors=$ac_res
+  ac_cv_search_setupterm=$ac_res
 else
   echo "$as_me: failed program was:" >&5
 sed 's/^/| /' conftest.$ac_ext >&5
 
 rm -f core conftest.err conftest.$ac_objext \
       conftest$ac_exeext
-  if test "${ac_cv_search_has_colors+set}" = set; then
+  if test "${ac_cv_search_setupterm+set}" = set; then
   break
 fi
 done
-if test "${ac_cv_search_has_colors+set}" = set; then
+if test "${ac_cv_search_setupterm+set}" = set; then
   :
 else
-  ac_cv_search_has_colors=no
+  ac_cv_search_setupterm=no
 fi
 rm conftest.$ac_ext
 LIBS=$ac_func_search_save_LIBS
 fi
-{ echo "$as_me:$LINENO: result: $ac_cv_search_has_colors" >&5
-echo "${ECHO_T}$ac_cv_search_has_colors" >&6; }
-ac_res=$ac_cv_search_has_colors
+{ echo "$as_me:$LINENO: result: $ac_cv_search_setupterm" >&5
+echo "${ECHO_T}$ac_cv_search_setupterm" >&6; }
+ac_res=$ac_cv_search_setupterm
 if test "$ac_res" != no; then
   test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
 
 cat >>confdefs.h <<\_ACEOF
-#define HAVE_CURSES 1
+#define HAVE_TERMINFO 1
 _ACEOF
 
 fi
@@ -16543,13 +16543,14 @@ else
 
 fi
 
-if test "$llvm_cv_enable_curses" = "yes" ; then
+if test "$llvm_cv_enable_terminfo" = "yes" ; then
+
 
 
 
 
 
-for ac_header in curses.h ncurses.h ncursesw.h ncurses/curses.h ncursesw/curses.h
+for ac_header in term.h curses.h ncurses.h ncursesw.h ncurses/curses.h ncursesw/curses.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
 if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
index 4b0aa4b..5090a65 100644 (file)
@@ -48,9 +48,6 @@
 /* Define to 1 if you have the `closedir' function. */
 #cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR}
 
-/* Define if curses provides the has_color() function on this platform. */
-#cmakedefine HAVE_CURSES
-
 /* Define to 1 if you have the <curses.h> header file. */
 #cmakedefine HAVE_CURSES_H
 
 /* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
 #cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H}
 
+/* Define if the setupterm() function is supported this platform. */
+#cmakedefine HAVE_TERMINFO ${HAVE_TERMINFO}
+
 /* Define to 1 if you have the <termios.h> header file. */
 #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H}
 
+/* Define to 1 if you have the <term.h> header file. */
+#cmakedefine HAVE_TERM_H
+
 /* Define if the neat program is available */
 #cmakedefine HAVE_TWOPI ${HAVE_TWOPI}
 
index 7bb1caa..55c66cc 100644 (file)
@@ -69,9 +69,6 @@
 /* can use __crashreporter_info__ */
 #undef HAVE_CRASHREPORTER_INFO
 
-/* Define if curses provides the has_color() function on this platform. */
-#undef HAVE_CURSES
-
 /* Define to 1 if you have the <curses.h> header file. */
 #undef HAVE_CURSES_H
 
 /* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
 #undef HAVE_SYS_WAIT_H
 
+/* Define if the setupterm() function is supported this platform. */
+#undef HAVE_TERMINFO
+
 /* Define to 1 if you have the <termios.h> header file. */
 #undef HAVE_TERMIOS_H
 
+/* Define to 1 if you have the <term.h> header file. */
+#undef HAVE_TERM_H
+
 /* Define if the neat program is available */
 #undef HAVE_TWOPI
 
index 0a797f6..1bb3e22 100644 (file)
 #  include <termios.h>
 #endif
 
-// See if we can use curses to detect information about a terminal when
-// connected to one.
-#ifdef HAVE_CURSES
+// Pull in the headers we found to go with the terminfo reading library (tinfo,
+// curses, whatever it may be). We have to pull in the 'curses.h' header as the
+// SysV spec only provides certain values and defines from that header even
+// though we work hard to not link against all of the curses implementation
+// when avoidable.
+#ifdef HAVE_TERMINFO
 # if defined(HAVE_CURSES_H)
 #  include <curses.h>
 # elif defined(HAVE_NCURSES_H)
 #  include <ncurses/curses.h>
 # elif defined(HAVE_NCURSESW_CURSES_H)
 #  include <ncursesw/curses.h>
-# else
-#  error Have a curses library but unable to find a curses header!
 # endif
-# include <term.h>
+# if defined(HAVE_TERM_H)
+#  include <term.h>
+# endif
 #endif
 
 //===----------------------------------------------------------------------===//
@@ -267,9 +270,8 @@ unsigned Process::StandardErrColumns() {
 }
 
 static bool terminalHasColors(int fd) {
-#ifdef HAVE_CURSES
-  // First, acquire a global lock because the curses C routines are thread
-  // hostile.
+#ifdef HAVE_TERMINFO
+  // First, acquire a global lock because these C routines are thread hostile.
   static sys::Mutex M;
   MutexGuard G(M);
 
@@ -279,8 +281,20 @@ static bool terminalHasColors(int fd) {
     // colors.
     return false;
 
-  // Test whether the terminal as set up supports color output.
-  if (has_colors() == TRUE)
+  // Test whether the terminal as set up supports color output. How to do this
+  // isn't entirely obvious. We can use the curses routine 'has_colors' but it
+  // would be nice to avoid a dependency on curses proper when we can make do
+  // with a minimal terminfo parsing library. Also, we don't really care whether
+  // the terminal supports the curses-specific color changing routines, merely
+  // if it will interpret ANSI color escape codes in a reasonable way. Thus, the
+  // strategy here is just to query the baseline colors capability and if it
+  // supports colors at all to assume it will translate the escape codes into
+  // whatever range of colors it does support. We can add more detailed tests
+  // here if users report them as necessary.
+  //
+  // The 'tigetnum' routine returns -2 or -1 on errors, and might return 0 if
+  // the terminfo says that no colors are supported.
+  if (tigetnum("colors") > 0)
     return true;
 #endif