@ 261102.1

140416.1 · d056668f4f4e0c2286354329b30d73d208d65c5e

Add autoconf checks for pthreads; fix #340

reading declarations

config/m4/find-func-no-libs.m4

new file mode 100644@@ -0,0 +1,8 @@+dnl Shamelessly stolen from Heimdal+dnl+dnl Look for function in any of the specified libraries+dnl++dnl AC_FIND_FUNC_NO_LIBS(func, libraries, includes, arguments, extra libs, extra args)+AC_DEFUN([AC_FIND_FUNC_NO_LIBS], [+AC_FIND_FUNC_NO_LIBS2([$1], ["" $2], [$3], [$4], [$5], [$6])])

config/m4/find-func-no-libs2.m4

new file mode 100644@@ -0,0 +1,62 @@+dnl Shamelessly stolen from Heimdal+dnl+dnl Look for function in any of the specified libraries+dnl++dnl AC_FIND_FUNC_NO_LIBS2(func, libraries, includes, arguments, extra libs, extra args)+AC_DEFUN([AC_FIND_FUNC_NO_LIBS2], [++AC_MSG_CHECKING([for $1])+AC_CACHE_VAL(ac_cv_funclib_$1,+[+if eval "test \"\$ac_cv_func_$1\" != yes" ; then+	ac_save_LIBS="$LIBS"+	for ac_lib in $2; do+		case "$ac_lib" in+		"") ;;+		yes) ac_lib="" ;;+		no) continue ;;+		-l*) ;;+		*) ac_lib="-l$ac_lib" ;;+		esac+		LIBS="$6 $ac_lib $5 $ac_save_LIBS"+		AC_LINK_IFELSE([AC_LANG_PROGRAM([[$3]],[[$1($4)]])],[eval "if test -n \"$ac_lib\";then ac_cv_funclib_$1=$ac_lib; else ac_cv_funclib_$1=yes; fi";break])+	done+	eval "ac_cv_funclib_$1=\${ac_cv_funclib_$1-no}"+	LIBS="$ac_save_LIBS"+fi+])++eval "ac_res=\$ac_cv_funclib_$1"++if false; then+	AC_CHECK_FUNCS($1)+dnl	AC_CHECK_LIBS($2, foo)+fi+# $1+eval "ac_tr_func=HAVE_[]upcase($1)"+eval "ac_tr_lib=HAVE_LIB[]upcase($ac_res | sed -e 's/-l//')"+eval "LIB_$1=$ac_res"++case "$ac_res" in+	yes)+	eval "ac_cv_func_$1=yes"+	eval "LIB_$1="+	AC_DEFINE_UNQUOTED($ac_tr_func)+	AC_MSG_RESULT([yes])+	;;+	no)+	eval "ac_cv_func_$1=no"+	eval "LIB_$1="+	AC_MSG_RESULT([no])+	;;+	*)+	eval "ac_cv_func_$1=yes"+	eval "ac_cv_lib_`echo "$ac_res" | sed 's/-l//'`=yes"+	AC_DEFINE_UNQUOTED($ac_tr_func)+	AC_DEFINE_UNQUOTED($ac_tr_lib)+	AC_MSG_RESULT([yes, in $ac_res])+	;;+esac+AC_SUBST(LIB_$1)+])

config/m4/find-func.m4

new file mode 100644@@ -0,0 +1,9 @@+dnl Shamelessly stolen from Heimdal+dnl+dnl AC_FIND_FUNC(func, libraries, includes, arguments)+AC_DEFUN([AC_FIND_FUNC], [+AC_FIND_FUNC_NO_LIBS([$1], [$2], [$3], [$4])+if test -n "$LIB_$1"; then+	LIBS="$LIB_$1 $LIBS"+fi+])

config/m4/misc.m4

new file mode 100644@@ -0,0 +1,3 @@++dnl Shamelessly stolen from Heimdal+AC_DEFUN([upcase],[`echo $1 | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`])dnl

configure.ac

@@ -78,6 +78,24 @@ EOF ])  AM_CONDITIONAL([ENABLE_DOCS], [test "x$enable_docs" != xno])++AC_FIND_FUNC([pthread_key_create], [pthread], [#include <pthread.h>], [NULL, NULL])+AC_FIND_FUNC([pthread_once], [pthread], [#include <pthread.h>], [NULL, NULL])+AC_FIND_FUNC([atexit], [pthread], [#include <stdlib.h>], [NULL])++dnl Thread local storage+have___thread=no+AC_MSG_CHECKING(for thread-local storage)+AC_LINK_IFELSE([AC_LANG_SOURCE([+static __thread int x ;+int main () { x = 123; return x; }+])], have___thread=yes)+if test $have___thread = yes; then +   AC_DEFINE([HAVE___THREAD],1,[Define to 1 if the system supports __thread])+fi+AC_MSG_RESULT($have___thread)++ AC_SUBST([BUNDLER], ["$bundle_cmd"])  AC_CONFIG_MACRO_DIR([config/m4])

jv_alloc.c

@@ -7,13 +7,27 @@ struct nomem_handler {     void *data; }; -#ifndef USE_PTHREAD_KEY+#if !defined(HAVE_PTHREAD_KEY_CREATE) || \+    !defined(HAVE_PTHREAD_ONCE) || \+    !defined(HAVE_ATEXIT)++/* Try thread-local storage? */+ #ifdef _MSC_VER+/* Visual C++: yes */ static __declspec(thread) struct nomem_handler nomem_handler;+#define USE_TLS #else+#ifdef HAVE___THREAD+/* GCC and friends: yes */ static __thread struct nomem_handler nomem_handler;-#endif+#define USE_TLS+#endif /* HAVE___THREAD */+#endif /* _MSC_VER */ +#endif /* !HAVE_PTHREAD_KEY_CREATE */++#ifdef USE_TLS void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {   nomem_handler.handler = handler; }@@ -25,44 +39,60 @@ static void memory_exhausted() {   fprintf(stderr, "error: cannot allocate memory\n");   abort(); }-#else+#else /* USE_TLS */+ #ifdef HAVE_PTHREAD_KEY_CREATE #include <pthread.h>  pthread_key_t nomem_handler_key; pthread_once_t mem_once = PTHREAD_ONCE_INIT; +static void tsd_fini(void) {+  struct nomem_handler *nomem_handler;+  nomem_handler = pthread_getspecific(nomem_handler_key);+  if (nomem_handler) {+    (void) pthread_setspecific(nomem_handler_key, NULL);+    free(nomem_handler);+  }+}+ static void tsd_init(void) {   if (pthread_key_create(&nomem_handler_key, NULL) != 0) {     fprintf(stderr, "error: cannot create thread specific key");     abort();   }+  if (atexit(tsd_fini) != 0) {+    fprintf(stderr, "error: cannot set an exit handler");+    abort();+  }+  struct nomem_handler *nomem_handler = calloc(1, sizeof(struct nomem_handler));+  if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) {+    fprintf(stderr, "error: cannot set thread specific data");+    abort();+  } }  void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {   pthread_once(&mem_once, tsd_init); // cannot fail-  struct nomem_handler *nomem_handler = calloc(1, sizeof (nomem_handler));+  struct nomem_handler *nomem_handler;++  nomem_handler = pthread_getspecific(nomem_handler_key);   if (nomem_handler == NULL) {     handler(data);     fprintf(stderr, "error: cannot allocate memory\n");     abort();   }-  nomem_handler.handler = handler;-  nomem_handler.data = data;-  if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) {-    handler(data);-    fprintf(stderr, "error: cannot set thread specific data");-    abort();-  }+  nomem_handler->handler = handler;+  nomem_handler->data = data; }  static void memory_exhausted() {-  jv_nomem_handler_f handler;+  struct nomem_handler *nomem_handler;    pthread_once(&mem_once, tsd_init);-  handler = pthread_getspecific(nomem_handler_key);-  if (handler)-    handler(); // Maybe handler() will longjmp() to safety+  nomem_handler = pthread_getspecific(nomem_handler_key);+  if (nomem_handler)+    nomem_handler->handler(nomem_handler->data); // Maybe handler() will longjmp() to safety   // Or not   fprintf(stderr, "error: cannot allocate memory\n");   abort();@@ -70,6 +100,8 @@ static void memory_exhausted() {  #else +/* No thread-local storage of any kind that we know how to handle */+ static struct nomem_handler nomem_handler; void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {   nomem_handler.handler = handler;@@ -82,7 +114,7 @@ static void memory_exhausted() { }  #endif /* HAVE_PTHREAD_KEY_CREATE */-#endif /* !USE_PTHREAD_KEY */+#endif /* USE_TLS */   void* jv_mem_alloc(size_t sz) {

setup.sh

@@ -9,7 +9,9 @@  if [ "clean" == "$1" ]; then   make distclean || echo "continuing..."-  rm -rf tmp autom4te.cache config+  find config/m4 -type f \( -name libtool\* -o -name lt\* \) | xargs rm -f+  find config -name m4 -prune -o -type f -print | xargs rm -f+  rm -rf tmp autom4te.cache   rm -f INSTALL Makefile.in aclocal.m4 configure config.h.in ChangeLog   rm -f jv_utf8_tables.gen.h lexer.c lexer.h parser.c parser.h elif [ "superclean" == "$1" ]; then