diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | autoconf/configure.ac | 24 | ||||
-rwxr-xr-x | cmake/config-ix.cmake | 19 | ||||
-rw-r--r-- | cmake/modules/LLVM-Config.cmake | 9 | ||||
-rw-r--r-- | cmake/modules/LLVMConfig.cmake.in | 2 | ||||
-rwxr-xr-x | configure | 300 | ||||
-rw-r--r-- | include/llvm/Config/config.h.cmake | 18 | ||||
-rw-r--r-- | include/llvm/Config/config.h.in | 18 | ||||
-rw-r--r-- | lib/Support/Unix/Process.inc | 51 |
9 files changed, 432 insertions, 11 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 687176c..a0a6c75 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,6 +123,8 @@ 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_THREADS "Use threads if available." ON) option(LLVM_ENABLE_ZLIB "Use zlib for compression/decompression if available." ON) diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 5be25af..30481ea 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -1072,6 +1072,17 @@ 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)]), + [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"]) ;; + esac], + llvm_cv_enable_curses="yes") + dnl --enable-libffi : check whether the user wants to turn off libffi: AC_ARG_ENABLE(libffi,AS_HELP_STRING( --enable-libffi,[Check for the presence of libffi (default is NO)]), @@ -1378,6 +1389,14 @@ dnl macros to detect whether clock_gettime is available, this just finds the 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 + 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.])) +fi + dnl libffi is optional; used to call external functions from the interpreter if test "$llvm_cv_enable_libffi" = "yes" ; then AC_SEARCH_LIBS(ffi_call,ffi,AC_DEFINE([HAVE_FFI_CALL],[1], @@ -1554,6 +1573,11 @@ else AC_SUBST(HAVE_LIBZ, 0) 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]) +fi + dnl Try to find ffi.h. if test "$llvm_cv_enable_libffi" = "yes" ; then AC_CHECK_HEADERS([ffi.h ffi/ffi.h]) diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index 85c4d81..0567820 100755 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -74,6 +74,12 @@ 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(curses.h HAVE_CURSES_H) +check_include_file(ncurses.h HAVE_NCURSES_H) +check_include_file(ncursesw.h HAVE_NCURSESW_H) +check_include_file(ncurses/curses.h HAVE_NCURSES_CURSES_H) +check_include_file(ncursesw/curses.h HAVE_NCURSESW_CURSES_H) + # library checks if( NOT PURE_WINDOWS ) check_library_exists(pthread pthread_create "" HAVE_LIBPTHREAD) @@ -97,6 +103,19 @@ 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}) + endif() + endif() + else() + set(HAVE_CURSES 0) + endif() endif() # function checks diff --git a/cmake/modules/LLVM-Config.cmake b/cmake/modules/LLVM-Config.cmake index 2ddc0b2..3e2447a 100644 --- a/cmake/modules/LLVM-Config.cmake +++ b/cmake/modules/LLVM-Config.cmake @@ -10,6 +10,15 @@ 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) + endif() + endif() if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) set(system_libs ${system_libs} pthread) endif() diff --git a/cmake/modules/LLVMConfig.cmake.in b/cmake/modules/LLVMConfig.cmake.in index f0b8c14..ae2bc59 100644 --- a/cmake/modules/LLVMConfig.cmake.in +++ b/cmake/modules/LLVMConfig.cmake.in @@ -20,6 +20,8 @@ set(TARGET_TRIPLE "@TARGET_TRIPLE@") set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@) +set(LLVM_ENABLE_CURSES @LLVM_ENABLE_CURSES@) + set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS@) set(LLVM_ENABLE_ZLIB @LLVM_ENABLE_ZLIB@) @@ -1453,6 +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-libffi Check for the presence of libffi (default is NO) --enable-ltdl-install install libltdl @@ -6004,6 +6006,20 @@ 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;} + { (exit 1); exit 1; }; } ;; + esac +else + llvm_cv_enable_curses="yes" +fi + + # Check whether --enable-libffi was given. if test "${enable_libffi+set}" = set; then enableval=$enable_libffi; case "$enableval" in @@ -10545,7 +10561,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF -#line 10548 "configure" +#line 10564 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12252,6 +12268,112 @@ 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 + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_func_search_save_LIBS=$LIBS +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* 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 has_colors (); +int +main () +{ +return has_colors (); + ; + return 0; +} +_ACEOF +for ac_lib in '' curses ncurses ncursesw; 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 + 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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_search_has_colors=$ac_res +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_has_colors+set}" = set; then + break +fi +done +if test "${ac_cv_search_has_colors+set}" = set; then + : +else + ac_cv_search_has_colors=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 +if test "$ac_res" != no; then + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +cat >>confdefs.h <<\_ACEOF +#define HAVE_CURSES 1 +_ACEOF + +fi + +fi + if test "$llvm_cv_enable_libffi" = "yes" ; then { echo "$as_me:$LINENO: checking for library containing ffi_call" >&5 echo $ECHO_N "checking for library containing ffi_call... $ECHO_C" >&6; } @@ -16421,6 +16543,182 @@ else fi +if test "$llvm_cv_enable_curses" = "yes" ; then + + + + + +for ac_header in 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 + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +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 "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +fi + if test "$llvm_cv_enable_libffi" = "yes" ; then diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index b34c404..4b0aa4b 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -48,6 +48,12 @@ /* 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 the <cxxabi.h> header file. */ #cmakedefine HAVE_CXXABI_H ${HAVE_CXXABI_H} @@ -256,6 +262,18 @@ /* Define if mmap() can map files into memory */ #undef HAVE_MMAP_FILE +/* Define to 1 if you have the <ncursesw/curses.h> header file. */ +#cmakedefine HAVE_NCURSESW_CURSES_H + +/* Define to 1 if you have the <ncursesw.h> header file. */ +#cmakedefine HAVE_NCURSESW_H + +/* Define to 1 if you have the <ncurses/curses.h> header file. */ +#cmakedefine HAVE_NCURSES_CURSES_H + +/* Define to 1 if you have the <ncurses.h> header file. */ +#cmakedefine HAVE_NCURSES_H + /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ #cmakedefine HAVE_NDIR_H ${HAVE_NDIR_H} diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 74b7829..7bb1caa 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -69,6 +69,12 @@ /* 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 the <cxxabi.h> header file. */ #undef HAVE_CXXABI_H @@ -282,6 +288,18 @@ /* Define if mmap() can map files into memory */ #undef HAVE_MMAP_FILE +/* Define to 1 if you have the <ncursesw/curses.h> header file. */ +#undef HAVE_NCURSESW_CURSES_H + +/* Define to 1 if you have the <ncursesw.h> header file. */ +#undef HAVE_NCURSESW_H + +/* Define to 1 if you have the <ncurses/curses.h> header file. */ +#undef HAVE_NCURSES_CURSES_H + +/* Define to 1 if you have the <ncurses.h> header file. */ +#undef HAVE_NCURSES_H + /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ #undef HAVE_NDIR_H diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index 1335b78..0a797f6 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -13,6 +13,8 @@ #include "Unix.h" #include "llvm/ADT/Hashing.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/MutexGuard.h" #include "llvm/Support/TimeValue.h" #ifdef HAVE_SYS_TIME_H #include <sys/time.h> @@ -36,6 +38,25 @@ # include <termios.h> #endif +// See if we can use curses to detect information about a terminal when +// connected to one. +#ifdef HAVE_CURSES +# if defined(HAVE_CURSES_H) +# include <curses.h> +# elif defined(HAVE_NCURSES_H) +# include <ncurses.h> +# elif defined(HAVE_NCURSESW_H) +# include <ncursesw.h> +# elif defined(HAVE_NCURSES_CURSES_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> +#endif + //===----------------------------------------------------------------------===// //=== WARNING: Implementation here must contain only generic UNIX code that //=== is guaranteed to work on *all* UNIX variants. @@ -245,22 +266,32 @@ unsigned Process::StandardErrColumns() { return getColumns(2); } -static bool terminalHasColors() { - if (const char *term = std::getenv("TERM")) { - // Most modern terminals support ANSI escape sequences for colors. - // We could check terminfo, or have a list of known terms that support - // colors, but that would be overkill. - // The user can always ask for no colors by setting TERM to dumb, or - // using a commandline flag. - return strcmp(term, "dumb") != 0; - } +static bool terminalHasColors(int fd) { +#ifdef HAVE_CURSES + // First, acquire a global lock because the curses C routines are thread + // hostile. + static sys::Mutex M; + MutexGuard G(M); + + int errret = 0; + if (setupterm((char *)0, fd, &errret) != OK) + // Regardless of why, if we can't get terminfo, we shouldn't try to print + // colors. + return false; + + // Test whether the terminal as set up supports color output. + if (has_colors() == TRUE) + return true; +#endif + + // Otherwise, be conservative. return false; } bool Process::FileDescriptorHasColors(int fd) { // A file descriptor has colors if it is displayed and the terminal has // colors. - return FileDescriptorIsDisplayed(fd) && terminalHasColors(); + return FileDescriptorIsDisplayed(fd) && terminalHasColors(fd); } bool Process::StandardOutHasColors() { |