diff --git a/mio/Makefile.in b/mio/Makefile.in index c3bfc6b..2fe5d77 100644 --- a/mio/Makefile.in +++ b/mio/Makefile.in @@ -300,6 +300,7 @@ SOCKET_LIBS = @SOCKET_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ UNICOWS_LIBS = @UNICOWS_LIBS@ +UNWIND_LIBS = @UNWIND_LIBS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ @@ -346,6 +347,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -576,7 +578,7 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir @@ -602,7 +604,7 @@ dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -620,7 +622,7 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -630,7 +632,7 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac diff --git a/mio/configure b/mio/configure index 8934747..0f780d6 100755 --- a/mio/configure +++ b/mio/configure @@ -649,6 +649,8 @@ MIO_SIZEOF_INT MIO_SIZEOF_LONG MIO_SIZEOF_LONG_LONG MIO_SIZEOF_WCHAR_T +ENABLE_LIBUNWIND_FALSE +ENABLE_LIBUNWIND_TRUE ENABLE_CXX_FALSE ENABLE_CXX_TRUE BUILD_MODE @@ -656,6 +658,7 @@ PACKAGE_VERSION_PATCH PACKAGE_VERSION_MINOR PACKAGE_VERSION_MAJOR QUADMATH_LIBS +UNWIND_LIBS SSL_LIBS UNICOWS_LIBS SENDFILE_LIBS @@ -768,6 +771,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -804,6 +808,7 @@ enable_ssl enable_debug enable_unicode enable_cxx +enable_libunwind ' ac_precious_vars='build_alias host_alias @@ -857,6 +862,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1109,6 +1115,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1246,7 +1261,7 @@ fi 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 + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1399,6 +1414,7 @@ Fine tuning of the installation directories: --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] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1455,6 +1471,7 @@ Optional Features: no:4 (default. yes) --enable-cxx build the library for C++ if a C++ compiler is available (default. yes) + --enable-libunwind use libunwind(default. no) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -18646,6 +18663,57 @@ done fi +if test "x${ac_cv_header_libunwind_h}" = "xyes" +then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for unw_backtrace in -lunwind" >&5 +$as_echo_n "checking for unw_backtrace in -lunwind... " >&6; } +if ${ac_cv_lib_unwind_unw_backtrace+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lunwind $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 unw_backtrace (); +int +main () +{ +return unw_backtrace (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_unwind_unw_backtrace=yes +else + ac_cv_lib_unwind_unw_backtrace=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_unwind_unw_backtrace" >&5 +$as_echo "$ac_cv_lib_unwind_unw_backtrace" >&6; } +if test "x$ac_cv_lib_unwind_unw_backtrace" = xyes; then : + + UNWIND_LIBS="-lunwind" + +$as_echo "#define HAVE_UNWIND_LIB 1" >>confdefs.h + + + +fi + + +fi + ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` @@ -21581,10 +21649,8 @@ else fi - test "${HAVE_CXX}" = "yes" || enable_cxx_is="no" test "${ax_cv_cxx_have_std_namespace}" = "yes" || enable_cxx_is="no" - if test "${enable_cxx_is}" = "yes" ; then ENABLE_CXX_TRUE= ENABLE_CXX_FALSE='#' @@ -21594,6 +21660,35 @@ else fi + +# Check whether --enable-libunwind was given. +if test "${enable_libunwind+set}" = set; then : + enableval=$enable_libunwind; enable_libunwind_is=$enableval +else + enable_libunwind_is=no + +fi + +if test "x${enable_libunwind_is}" = "xyes" +then + if test "x${ac_cv_header_libunwind_h}" = "xyes" -a "${UNWIND_LIBS}" != "" + then + +$as_echo "#define MIO_ENABLE_LIBUNWIND /**/" >>confdefs.h + + else + enable_libunwind_is="no" + fi +fi + if test "x${enable_libunwind_is}" = "xyes"; then + ENABLE_LIBUNWIND_TRUE= + ENABLE_LIBUNWIND_FALSE='#' +else + ENABLE_LIBUNWIND_TRUE='#' + ENABLE_LIBUNWIND_FALSE= +fi + + MIO_SIZEOF_WCHAR_T=$ac_cv_sizeof_wchar_t MIO_SIZEOF_LONG_LONG=$ac_cv_sizeof_long_long @@ -21780,6 +21875,10 @@ if test -z "${ENABLE_CXX_TRUE}" && test -z "${ENABLE_CXX_FALSE}"; then as_fn_error $? "conditional \"ENABLE_CXX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${ENABLE_LIBUNWIND_TRUE}" && test -z "${ENABLE_LIBUNWIND_FALSE}"; then + as_fn_error $? "conditional \"ENABLE_LIBUNWIND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 diff --git a/mio/configure.ac b/mio/configure.ac index b821c07..c083e5d 100644 --- a/mio/configure.ac +++ b/mio/configure.ac @@ -303,6 +303,17 @@ then fi AC_SUBST(SSL_LIBS) +if test "x${ac_cv_header_libunwind_h}" = "xyes" +then + AC_CHECK_LIB([unwind], [unw_backtrace], + [ + UNWIND_LIBS="-lunwind" + AC_DEFINE([HAVE_UNWIND_LIB], [1], [libunwind is available]) + ] + ) + AC_SUBST(UNWIND_LIBS) +fi + AC_STRUCT_DIRENT_D_TYPE AC_CHECK_MEMBERS([DIR.d_fd, DIR.dd_fd],,,[[#include ]]) AC_CHECK_MEMBERS([struct stat.st_birthtime]) @@ -833,14 +844,29 @@ AC_ARG_ENABLE([cxx], enable_cxx_is=$enableval, enable_cxx_is=yes ) - dnl disable c++ if no c++ compiler was found test "${HAVE_CXX}" = "yes" || enable_cxx_is="no" dnl disable c++ if the compiler is too old. test "${ax_cv_cxx_have_std_namespace}" = "yes" || enable_cxx_is="no" - AM_CONDITIONAL(ENABLE_CXX, test "${enable_cxx_is}" = "yes" ) + +AC_ARG_ENABLE([libunwind], + [AS_HELP_STRING([--enable-libunwind],[use libunwind(default. no)])], + enable_libunwind_is=$enableval, + enable_libunwind_is=no +) +if test "x${enable_libunwind_is}" = "xyes" +then + if test "x${ac_cv_header_libunwind_h}" = "xyes" -a "${UNWIND_LIBS}" != "" + then + AC_DEFINE([MIO_ENABLE_LIBUNWIND],[],[use libunwind for backtracing stack frames]) + else + enable_libunwind_is="no" + fi +fi +AM_CONDITIONAL(ENABLE_LIBUNWIND, test "x${enable_libunwind_is}" = "xyes") + AC_SUBST(MIO_SIZEOF_WCHAR_T, $ac_cv_sizeof_wchar_t) AC_SUBST(MIO_SIZEOF_LONG_LONG, $ac_cv_sizeof_long_long) AC_SUBST(MIO_SIZEOF_LONG, $ac_cv_sizeof_long) diff --git a/mio/lib/Makefile.am b/mio/lib/Makefile.am index 8feddf8..5d5aa4f 100644 --- a/mio/lib/Makefile.am +++ b/mio/lib/Makefile.am @@ -40,6 +40,9 @@ libmio_la_SOURCES = \ mio-tmr.c \ sck-addr.c \ sck-addr.h \ + sys-ass.c \ + sys-err.c \ + sys-log.c \ utf8.c \ utl.c libmio_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) diff --git a/mio/lib/Makefile.in b/mio/lib/Makefile.in index 42e2053..9087fbd 100644 --- a/mio/lib/Makefile.in +++ b/mio/lib/Makefile.in @@ -143,7 +143,9 @@ libmio_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) am_libmio_la_OBJECTS = libmio_la-err.lo libmio_la-logfmt.lo \ libmio_la-mio.lo libmio_la-mio-pro.lo libmio_la-mio-sck.lo \ libmio_la-mio-tim.lo libmio_la-mio-tmr.lo \ - libmio_la-sck-addr.lo libmio_la-utf8.lo libmio_la-utl.lo + libmio_la-sck-addr.lo libmio_la-sys-ass.lo \ + libmio_la-sys-err.lo libmio_la-sys-log.lo libmio_la-utf8.lo \ + libmio_la-utl.lo libmio_la_OBJECTS = $(am_libmio_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -316,6 +318,7 @@ SOCKET_LIBS = @SOCKET_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ UNICOWS_LIBS = @UNICOWS_LIBS@ +UNWIND_LIBS = @UNWIND_LIBS@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ @@ -362,6 +365,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -409,6 +413,9 @@ libmio_la_SOURCES = \ mio-tmr.c \ sck-addr.c \ sck-addr.h \ + sys-ass.c \ + sys-err.c \ + sys-log.c \ utf8.c \ utl.c @@ -574,6 +581,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-mio-tmr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-mio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-sck-addr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-sys-ass.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-sys-err.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-sys-log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-utf8.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmio_la-utl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio-main.Po@am__quote@ @@ -658,6 +668,27 @@ libmio_la-sck-addr.lo: sck-addr.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmio_la-sck-addr.lo `test -f 'sck-addr.c' || echo '$(srcdir)/'`sck-addr.c +libmio_la-sys-ass.lo: sys-ass.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmio_la-sys-ass.lo -MD -MP -MF $(DEPDIR)/libmio_la-sys-ass.Tpo -c -o libmio_la-sys-ass.lo `test -f 'sys-ass.c' || echo '$(srcdir)/'`sys-ass.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-sys-ass.Tpo $(DEPDIR)/libmio_la-sys-ass.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sys-ass.c' object='libmio_la-sys-ass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmio_la-sys-ass.lo `test -f 'sys-ass.c' || echo '$(srcdir)/'`sys-ass.c + +libmio_la-sys-err.lo: sys-err.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmio_la-sys-err.lo -MD -MP -MF $(DEPDIR)/libmio_la-sys-err.Tpo -c -o libmio_la-sys-err.lo `test -f 'sys-err.c' || echo '$(srcdir)/'`sys-err.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-sys-err.Tpo $(DEPDIR)/libmio_la-sys-err.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sys-err.c' object='libmio_la-sys-err.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmio_la-sys-err.lo `test -f 'sys-err.c' || echo '$(srcdir)/'`sys-err.c + +libmio_la-sys-log.lo: sys-log.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmio_la-sys-log.lo -MD -MP -MF $(DEPDIR)/libmio_la-sys-log.Tpo -c -o libmio_la-sys-log.lo `test -f 'sys-log.c' || echo '$(srcdir)/'`sys-log.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-sys-log.Tpo $(DEPDIR)/libmio_la-sys-log.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sys-log.c' object='libmio_la-sys-log.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libmio_la-sys-log.lo `test -f 'sys-log.c' || echo '$(srcdir)/'`sys-log.c + libmio_la-utf8.lo: utf8.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libmio_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libmio_la-utf8.lo -MD -MP -MF $(DEPDIR)/libmio_la-utf8.Tpo -c -o libmio_la-utf8.lo `test -f 'utf8.c' || echo '$(srcdir)/'`utf8.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmio_la-utf8.Tpo $(DEPDIR)/libmio_la-utf8.Plo diff --git a/mio/lib/err.c b/mio/lib/err.c index d1c7e35..9207add 100644 --- a/mio/lib/err.c +++ b/mio/lib/err.c @@ -78,208 +78,6 @@ const mio_ooch_t* mio_errnum_to_errstr (mio_errnum_t errnum) return (errnum >= 0 && errnum < MIO_COUNTOF(errstr))? errstr[errnum]: e_unknown; } -/* -------------------------------------------------------------------------- - * ERROR MESSAGE CONVERSION - * -------------------------------------------------------------------------- */ -#include - -static mio_errnum_t errno_to_errnum (int errcode) -{ - switch (errcode) - { - case ENOMEM: return MIO_ESYSMEM; - case EINVAL: return MIO_EINVAL; - - #if defined(EBUSY) - case EBUSY: return MIO_EBUSY; - #endif - case EACCES: return MIO_EACCES; - #if defined(EPERM) - case EPERM: return MIO_EPERM; - #endif - #if defined(ENOTDIR) - case ENOTDIR: return MIO_ENOTDIR; - #endif - case ENOENT: return MIO_ENOENT; - #if defined(EEXIST) - case EEXIST: return MIO_EEXIST; - #endif - #if defined(EINTR) - case EINTR: return MIO_EINTR; - #endif - - #if defined(EPIPE) - case EPIPE: return MIO_EPIPE; - #endif - - #if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN != EWOULDBLOCK) - case EAGAIN: - case EWOULDBLOCK: return MIO_EAGAIN; - #elif defined(EAGAIN) - case EAGAIN: return MIO_EAGAIN; - #elif defined(EWOULDBLOCK) - case EWOULDBLOCK: return MIO_EAGAIN; - #endif - - #if defined(EBADF) - case EBADF: return MIO_EBADHND; - #endif - - #if defined(EIO) - case EIO: return MIO_EIOERR; - #endif - - default: return MIO_ESYSERR; - } -} - -#if defined(_WIN32) -static mio_errnum_t winerr_to_errnum (DWORD errcode) -{ - switch (errcode) - { - case ERROR_NOT_ENOUGH_MEMORY: - case ERROR_OUTOFMEMORY: - return MIO_ESYSMEM; - - case ERROR_INVALID_PARAMETER: - case ERROR_INVALID_NAME: - return MIO_EINVAL; - - case ERROR_INVALID_HANDLE: - return MIO_EBADHND; - - case ERROR_ACCESS_DENIED: - case ERROR_SHARING_VIOLATION: - return MIO_EACCES; - - #if defined(ERROR_IO_PRIVILEGE_FAILED) - case ERROR_IO_PRIVILEGE_FAILED: - #endif - case ERROR_PRIVILEGE_NOT_HELD: - return MIO_EPERM; - - case ERROR_FILE_NOT_FOUND: - case ERROR_PATH_NOT_FOUND: - return MIO_ENOENT; - - case ERROR_ALREADY_EXISTS: - case ERROR_FILE_EXISTS: - return MIO_EEXIST; - - case ERROR_BROKEN_PIPE: - return MIO_EPIPE; - - default: - return MIO_ESYSERR; - } -} -#endif - -#if defined(__OS2__) -static mio_errnum_t os2err_to_errnum (APIRET errcode) -{ - /* APIRET e */ - switch (errcode) - { - case ERROR_NOT_ENOUGH_MEMORY: - return MIO_ESYSMEM; - - case ERROR_INVALID_PARAMETER: - case ERROR_INVALID_NAME: - return MIO_EINVAL; - - case ERROR_INVALID_HANDLE: - return MIO_EBADHND; - - case ERROR_ACCESS_DENIED: - case ERROR_SHARING_VIOLATION: - return MIO_EACCES; - - case ERROR_FILE_NOT_FOUND: - case ERROR_PATH_NOT_FOUND: - return MIO_ENOENT; - - case ERROR_ALREADY_EXISTS: - return MIO_EEXIST; - - /*TODO: add more mappings */ - default: - return MIO_ESYSERR; - } -} -#endif - -#if defined(macintosh) -static mio_errnum_t macerr_to_errnum (int errcode) -{ - switch (e) - { - case notEnoughMemoryErr: - return MIO_ESYSMEM; - case paramErr: - return MIO_EINVAL; - - case qErr: /* queue element not found during deletion */ - case fnfErr: /* file not found */ - case dirNFErr: /* direcotry not found */ - case resNotFound: /* resource not found */ - case resFNotFound: /* resource file not found */ - case nbpNotFound: /* name not found on remove */ - return MIO_ENOENT; - - /*TODO: add more mappings */ - default: - return MIO_ESYSERR; - } -} -#endif - -static mio_errnum_t syserrstrb (mio_t* mio, int syserr_type, int syserr_code, mio_bch_t* buf, mio_oow_t len) -{ - switch (syserr_type) - { - case 1: - #if defined(_WIN32) - if (buf) - { - DWORD rc; - rc = FormatMessageA ( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, syserr_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - buf, len, MIO_NULL - ); - while (rc > 0 && buf[rc - 1] == '\r' || buf[rc - 1] == '\n') buf[--rc] = '\0'; - } - return winerr_to_errnum(syserr_code); - #elif defined(__OS2__) - /* TODO: convert code to string */ - if (buf) mio_copy_bcstr (buf, len, "system error"); - return os2err_to_errnum(syserr_code); - #elif defined(macintosh) - /* TODO: convert code to string */ - if (buf) mio_copy_bcstr (buf, len, "system error"); - return os2err_to_errnum(syserr_code); - #else - /* in other systems, errno is still the native system error code. - * fall thru */ - #endif - - case 0: - #if defined(HAVE_STRERROR_R) - if (buf) strerror_r (syserr_code, buf, len); - #else - /* this is not thread safe */ - if (buf) mio_copy_bcstr (buf, len, strerror(syserr_code)); - #endif - return errno_to_errnum(syserr_code); - } - - if (buf) mio_copy_bcstr (buf, len, "system error"); - return MIO_ESYSERR; -} - - /* -------------------------------------------------------------------------- * ERROR NUMBER/MESSAGE HANDLING * -------------------------------------------------------------------------- */ @@ -321,7 +119,7 @@ void mio_seterrwithsyserr (mio_t* mio, int syserr_type, int syserr_code) /*if (mio->vmprim.syserrstrb) {*/ - errnum = /*mio->vmprim.*/syserrstrb(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.bch, MIO_COUNTOF(mio->errmsg.tmpbuf.bch)); + errnum = /*mio->vmprim.*/mio_sys_syserrstrb(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.bch, MIO_COUNTOF(mio->errmsg.tmpbuf.bch)); mio_seterrbfmt (mio, errnum, "%hs", mio->errmsg.tmpbuf.bch); /* } @@ -344,7 +142,7 @@ void mio_seterrbfmtwithsyserr (mio_t* mio, int syserr_type, int syserr_code, con /* if (mio->vmprim.syserrstrb) {*/ - errnum = /*mio->vmprim.*/syserrstrb(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.bch, MIO_COUNTOF(mio->errmsg.tmpbuf.bch)); + errnum = mio_sys_syserrstrb(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.bch, MIO_COUNTOF(mio->errmsg.tmpbuf.bch)); va_start (ap, fmt); mio_seterrbfmtv (mio, errnum, fmt, ap); @@ -368,7 +166,7 @@ void mio_seterrbfmtwithsyserr (mio_t* mio, int syserr_type, int syserr_code, con else { MIO_ASSERT (mio, mio->vmprim.syserrstru != MIO_NULL); - errnum = mio->vmprim.syserrstru(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.uch, MIO_COUNTOF(mio->errmsg.tmpbuf.uch)); + errnum = mio_sys_syserrstru(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.uch, MIO_COUNTOF(mio->errmsg.tmpbuf.uch)); va_start (ap, fmt); mio_seterrbfmtv (mio, errnum, fmt, ap); @@ -401,7 +199,7 @@ void mio_seterrufmtwithsyserr (mio_t* mio, int syserr_type, int syserr_code, con /*if (mio->vmprim.syserrstrb) {*/ - errnum = /*mio->vmprim.*/syserrstrb(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.bch, MIO_COUNTOF(mio->errmsg.tmpbuf.bch)); + errnum = mio_sys_syserrstrb(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.bch, MIO_COUNTOF(mio->errmsg.tmpbuf.bch)); va_start (ap, fmt); mio_seterrufmtv (mio, errnum, fmt, ap); @@ -425,7 +223,7 @@ void mio_seterrufmtwithsyserr (mio_t* mio, int syserr_type, int syserr_code, con else { MIO_ASSERT (mio, mio->vmprim.syserrstru != MIO_NULL); - errnum = mio->vmprim.syserrstru(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.uch, MIO_COUNTOF(mio->errmsg.tmpbuf.uch)); + errnum = mio_sys_syserrstru(mio, syserr_type, syserr_code, mio->errmsg.tmpbuf.uch, MIO_COUNTOF(mio->errmsg.tmpbuf.uch)); va_start (ap, fmt); mio_seterrufmtv (mio, errnum, fmt, ap); diff --git a/mio/lib/logfmt.c b/mio/lib/logfmt.c index d572ecf..f30e30b 100644 --- a/mio/lib/logfmt.c +++ b/mio/lib/logfmt.c @@ -202,7 +202,7 @@ static int put_ooch (mio_t* mio, mio_bitmask_t mask, mio_ooch_t ch, mio_oow_t le /* no line ending - append a line terminator */ mio->log.ptr[mio->log.len++] = '\n'; } - vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); + prim_write_log (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); mio->log.len = 0; } @@ -246,7 +246,7 @@ redo: /* no line ending - append a line terminator */ mio->log.ptr[mio->log.len++] = '\n'; } - vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); + prim_write_log (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); mio->log.len = 0; } @@ -297,7 +297,7 @@ static int put_oocs (mio_t* mio, mio_bitmask_t mask, const mio_ooch_t* ptr, mio_ mio->log.ptr[mio->log.len++] = '\n'; } - vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); + prim_write_log (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); mio->log.len = 0; } @@ -341,7 +341,7 @@ redo: /* no line ending - append a line terminator */ mio->log.ptr[mio->log.len++] = '\n'; } - vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); + prim_write_log (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); mio->log.len = 0; } @@ -441,7 +441,7 @@ mio_ooi_t mio_logbfmt (mio_t* mio, mio_bitmask_t mask, const mio_bch_t* fmt, ... if (mio->log.len > 0 && mio->log.ptr[mio->log.len - 1] == '\n') { - vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); + prim_write_log (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); mio->log.len = 0; } return (x <= -1)? -1: fo.count; @@ -469,7 +469,7 @@ mio_ooi_t mio_logufmt (mio_t* mio, mio_bitmask_t mask, const mio_uch_t* fmt, ... if (mio->log.len > 0 && mio->log.ptr[mio->log.len - 1] == '\n') { - vmprim_log_write (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); + prim_write_log (mio, mio->log.last_mask, mio->log.ptr, mio->log.len); mio->log.len = 0; } diff --git a/mio/lib/mio-cfg.h.in b/mio/lib/mio-cfg.h.in index 7e189e6..dbd15b9 100644 --- a/mio/lib/mio-cfg.h.in +++ b/mio/lib/mio-cfg.h.in @@ -663,6 +663,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H +/* libunwind is available */ +#undef HAVE_UNWIND_LIB + /* Define to 1 if you have the `uselocale' function. */ #undef HAVE_USELOCALE @@ -729,6 +732,9 @@ /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR +/* use libunwind for backtracing stack frames */ +#undef MIO_ENABLE_LIBUNWIND + /* Use the unicode character type as the default character type */ #undef MIO_ENABLE_UNICODE diff --git a/mio/lib/mio-prv.h b/mio/lib/mio-prv.h index e38da16..9d8b9c7 100644 --- a/mio/lib/mio-prv.h +++ b/mio/lib/mio-prv.h @@ -33,7 +33,6 @@ /*TODO: redefine and remove these */ -#include #include #include /*TODO: redefine these */ @@ -41,7 +40,15 @@ #define MIO_MEMCPY(dst,src,count) memcpy(dst,src,count) #define MIO_MEMMOVE(dst,src,count) memmove(dst,src,count) #define MIO_MEMCMP(dst,src,count) memcmp(dst,src,count) -#define MIO_ASSERT assert + +/* ========================================================================= + * MIO ASSERTION + * ========================================================================= */ +#if defined(MIO_BUILD_RELEASE) +# define MIO_ASSERT(mio,expr) ((void)0) +#else +# define MIO_ASSERT(mio,expr) ((void)((expr) || mio_sys_assertfail(mio, #expr, __FILE__, __LINE__), 0))) +#endif #define MIO_EPOCH_YEAR (1970) @@ -63,6 +70,15 @@ #define MIO_SECS_PER_HOUR (MIO_SECS_PER_MIN*MIO_MINS_PER_HOUR) #define MIO_SECS_PER_DAY (MIO_SECS_PER_MIN*MIO_MINS_PER_DAY) +/* i don't want an error raised inside the callback to override + * the existing error number and message. */ +#define prim_write_log(mio,mask,ptr,len) do { \ + int shuterr = (mio)->shuterr; \ + (mio)->shuterr = 1; \ + mio_sys_writelog (mio, mask, ptr, len); \ + (mio)->shuterr = shuterr; \ + } while(0) + #ifdef __cplusplus extern "C" { #endif @@ -121,6 +137,29 @@ int mio_gettmrtmout ( mio_ntime_t* tmout ); +/* ========================================================================== */ +void mio_sys_assertfail ( + mio_t* mio, + const mio_bch_t* expr, + const mio_bch_t* file, + mio_oow_t line +); + +mio_errnum_t mio_sys_syserrstrb ( + mio_t* mio, + int syserr_type, + int syserr_code, + mio_bch_t* buf, + mio_oow_t len +); + +void mio_sys_writelog ( + mio_t* mio, + mio_bitmask_t mask, + const mio_ooch_t* msg, + mio_oow_t len +); + #ifdef __cplusplus } #endif diff --git a/mio/lib/mio.h b/mio/lib/mio.h index 427cd6e..37af758 100644 --- a/mio/lib/mio.h +++ b/mio/lib/mio.h @@ -368,13 +368,13 @@ enum mio_dev_event_t }; typedef enum mio_dev_event_t mio_dev_event_t; - - - - #define MIO_CWQFL_SIZE 16 #define MIO_CWQFL_ALIGN 16 +/* ========================================================================= */ + +/* ========================================================================= */ + typedef struct mio_mux_t mio_mux_t; struct mio_t diff --git a/mio/lib/sys-ass.c b/mio/lib/sys-ass.c new file mode 100644 index 0000000..94316fe --- /dev/null +++ b/mio/lib/sys-ass.c @@ -0,0 +1,174 @@ +/* + * $Id$ + * + Copyright (c) 2015-2016 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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 AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR 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. + */ + +#if defined(_WIN32) +# include +# include + +#elif defined(__OS2__) +# define INCL_DOSERRORS +# include +# include + +#elif defined(__DOS__) +# include +# include + +# if defined(_INTELC32_) +# define DOS_EXIT 0x4C +# include +# include +# else +# include +# endif + +#elif defined(macintosh) +# include +# include +# include + +# include +# include +# include +# include + + /* TODO: a lot to do */ + +#elif defined(vms) || defined(__vms) +# define __NEW_STARLET 1 +# include /* (SYS$...) */ +# include /* (SS$...) */ +# include /* (lib$...) */ + + /* TODO: a lot to do */ + +#else +# include +# include +# include +#endif + +#if defined(MIO_BUILD_RELEASE) + +void mio_sys_assertfail (mio_t* mio, const mio_bch_t* expr, const mio_bch_t* file, mio_oow_t line) +{ + /* do nothing */ +} + +#else /* defined(MIO_BUILD_RELEASE) */ + +#if defined(MIO_ENABLE_LIBUNWIND) +#include +static void backtrace_stack_frames (mio_t* mio) +{ + unw_cursor_t cursor; + unw_context_t context; + int n; + + unw_getcontext(&context); + unw_init_local(&cursor, &context); + + mio_logbfmt (mio, MIO_LOG_UNTYPED | MIO_LOG_DEBUG, "[BACKTRACE]\n"); + for (n = 0; unw_step(&cursor) > 0; n++) + { + unw_word_t ip, sp, off; + char symbol[256]; + + unw_get_reg (&cursor, UNW_REG_IP, &ip); + unw_get_reg (&cursor, UNW_REG_SP, &sp); + + if (unw_get_proc_name(&cursor, symbol, MIO_COUNTOF(symbol), &off)) + { + mio_copy_bcstr (symbol, MIO_COUNTOF(symbol), ""); + } + + mio_logbfmt (mio, MIO_LOG_UNTYPED | MIO_LOG_DEBUG, + "#%02d ip=0x%*p sp=0x%*p %s+0x%zu\n", + n, MIO_SIZEOF(void*) * 2, (void*)ip, MIO_SIZEOF(void*) * 2, (void*)sp, symbol, (mio_oow_t)off); + } +} +#elif defined(HAVE_BACKTRACE) +#include +static void backtrace_stack_frames (mio_t* mio) +{ + void* btarray[128]; + mio_oow_t btsize; + char** btsyms; + + btsize = backtrace (btarray, MIO_COUNTOF(btarray)); + btsyms = backtrace_symbols (btarray, btsize); + if (btsyms) + { + mio_oow_t i; + mio_logbfmt (mio, MIO_LOG_UNTYPED | MIO_LOG_DEBUG, "[BACKTRACE]\n"); + + for (i = 0; i < btsize; i++) + { + mio_logbfmt(mio, MIO_LOG_UNTYPED | MIO_LOG_DEBUG, " %s\n", btsyms[i]); + } + free (btsyms); + } +} +#else +static void backtrace_stack_frames (mio_t* mio) +{ + /* do nothing. not supported */ +} +#endif /* defined(MIO_ENABLE_LIBUNWIND) */ + +void mio_sys_assertfail (mio_t* mio, const mio_bch_t* expr, const mio_bch_t* file, mio_oow_t line) +{ + mio_logbfmt (mio, MIO_LOG_UNTYPED | MIO_LOG_FATAL, "ASSERTION FAILURE: %s at %s:%zu\n", expr, file, line); + backtrace_stack_frames (mio); + +#if defined(_WIN32) + ExitProcess (249); +#elif defined(__OS2__) + DosExit (EXIT_PROCESS, 249); +#elif defined(__DOS__) + { + union REGS regs; + regs.h.ah = DOS_EXIT; + regs.h.al = 249; + intdos (®s, ®s); + } +#elif defined(vms) || defined(__vms) + lib$stop (SS$_ABORT); /* use SS$_OPCCUS instead? */ + /* this won't be reached since lib$stop() terminates the process */ + sys$exit (SS$_ABORT); /* this condition code can be shown with + * 'show symbol $status' from the command-line. */ +#elif defined(macintosh) + + ExitToShell (); + +#else + + kill (getpid(), SIGABRT); + _exit (1); +#endif +} + +#endif /* defined(MIO_BUILD_RELEASE) */ diff --git a/mio/lib/sys-err.c b/mio/lib/sys-err.c new file mode 100644 index 0000000..600d8a9 --- /dev/null +++ b/mio/lib/sys-err.c @@ -0,0 +1,226 @@ +/* + * $Id$ + * + Copyright (c) 2015-2016 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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 AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR 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 "mio-prv.h" + +#include + +static mio_errnum_t errno_to_errnum (int errcode) +{ + switch (errcode) + { + case ENOMEM: return MIO_ESYSMEM; + case EINVAL: return MIO_EINVAL; + + #if defined(EBUSY) + case EBUSY: return MIO_EBUSY; + #endif + case EACCES: return MIO_EACCES; + #if defined(EPERM) + case EPERM: return MIO_EPERM; + #endif + #if defined(ENOTDIR) + case ENOTDIR: return MIO_ENOTDIR; + #endif + case ENOENT: return MIO_ENOENT; + #if defined(EEXIST) + case EEXIST: return MIO_EEXIST; + #endif + #if defined(EINTR) + case EINTR: return MIO_EINTR; + #endif + + #if defined(EPIPE) + case EPIPE: return MIO_EPIPE; + #endif + + #if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN != EWOULDBLOCK) + case EAGAIN: + case EWOULDBLOCK: return MIO_EAGAIN; + #elif defined(EAGAIN) + case EAGAIN: return MIO_EAGAIN; + #elif defined(EWOULDBLOCK) + case EWOULDBLOCK: return MIO_EAGAIN; + #endif + + #if defined(EBADF) + case EBADF: return MIO_EBADHND; + #endif + + #if defined(EIO) + case EIO: return MIO_EIOERR; + #endif + + default: return MIO_ESYSERR; + } +} + +#if defined(_WIN32) +static mio_errnum_t winerr_to_errnum (DWORD errcode) +{ + switch (errcode) + { + case ERROR_NOT_ENOUGH_MEMORY: + case ERROR_OUTOFMEMORY: + return MIO_ESYSMEM; + + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_NAME: + return MIO_EINVAL; + + case ERROR_INVALID_HANDLE: + return MIO_EBADHND; + + case ERROR_ACCESS_DENIED: + case ERROR_SHARING_VIOLATION: + return MIO_EACCES; + + #if defined(ERROR_IO_PRIVILEGE_FAILED) + case ERROR_IO_PRIVILEGE_FAILED: + #endif + case ERROR_PRIVILEGE_NOT_HELD: + return MIO_EPERM; + + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + return MIO_ENOENT; + + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + return MIO_EEXIST; + + case ERROR_BROKEN_PIPE: + return MIO_EPIPE; + + default: + return MIO_ESYSERR; + } +} +#endif + +#if defined(__OS2__) +static mio_errnum_t os2err_to_errnum (APIRET errcode) +{ + /* APIRET e */ + switch (errcode) + { + case ERROR_NOT_ENOUGH_MEMORY: + return MIO_ESYSMEM; + + case ERROR_INVALID_PARAMETER: + case ERROR_INVALID_NAME: + return MIO_EINVAL; + + case ERROR_INVALID_HANDLE: + return MIO_EBADHND; + + case ERROR_ACCESS_DENIED: + case ERROR_SHARING_VIOLATION: + return MIO_EACCES; + + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + return MIO_ENOENT; + + case ERROR_ALREADY_EXISTS: + return MIO_EEXIST; + + /*TODO: add more mappings */ + default: + return MIO_ESYSERR; + } +} +#endif + +#if defined(macintosh) +static mio_errnum_t macerr_to_errnum (int errcode) +{ + switch (e) + { + case notEnoughMemoryErr: + return MIO_ESYSMEM; + case paramErr: + return MIO_EINVAL; + + case qErr: /* queue element not found during deletion */ + case fnfErr: /* file not found */ + case dirNFErr: /* direcotry not found */ + case resNotFound: /* resource not found */ + case resFNotFound: /* resource file not found */ + case nbpNotFound: /* name not found on remove */ + return MIO_ENOENT; + + /*TODO: add more mappings */ + default: + return MIO_ESYSERR; + } +} +#endif + +mio_errnum_t mio_sys_syserrstrb (mio_t* mio, int syserr_type, int syserr_code, mio_bch_t* buf, mio_oow_t len) +{ + switch (syserr_type) + { + case 1: + #if defined(_WIN32) + if (buf) + { + DWORD rc; + rc = FormatMessageA ( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, syserr_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buf, len, MIO_NULL + ); + while (rc > 0 && buf[rc - 1] == '\r' || buf[rc - 1] == '\n') buf[--rc] = '\0'; + } + return winerr_to_errnum(syserr_code); + #elif defined(__OS2__) + /* TODO: convert code to string */ + if (buf) mio_copy_bcstr (buf, len, "system error"); + return os2err_to_errnum(syserr_code); + #elif defined(macintosh) + /* TODO: convert code to string */ + if (buf) mio_copy_bcstr (buf, len, "system error"); + return os2err_to_errnum(syserr_code); + #else + /* in other systems, errno is still the native system error code. + * fall thru */ + #endif + + case 0: + #if defined(HAVE_STRERROR_R) + if (buf) strerror_r (syserr_code, buf, len); + #else + /* this is not thread safe */ + if (buf) mio_copy_bcstr (buf, len, strerror(syserr_code)); + #endif + return errno_to_errnum(syserr_code); + } + + if (buf) mio_copy_bcstr (buf, len, "system error"); + return MIO_ESYSERR; +} + diff --git a/mio/lib/sys-log.c b/mio/lib/sys-log.c new file mode 100644 index 0000000..af0bd47 --- /dev/null +++ b/mio/lib/sys-log.c @@ -0,0 +1,261 @@ +/* + * $Id$ + * + Copyright (c) 2015-2016 Chung, Hyung-Hwan. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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 AUTHOR "AS IS" AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR 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 "mio-prv.h" + +static int write_all (int fd, const mio_bch_t* ptr, mio_oow_t len) +{ + while (len > 0) + { + mio_ooi_t wr; + + wr = write(fd, ptr, len); + + if (wr <= -1) + { + #if defined(EAGAIN) && defined(EWOULDBLOCK) && (EAGAIN == EWOULDBLOCK) + if (errno == EAGAIN) continue; + #else + #if defined(EAGAIN) + if (errno == EAGAIN) continue; + #elif defined(EWOULDBLOCK) + if (errno == EWOULDBLOCK) continue; + #endif + #endif + + #if defined(EINTR) + /* TODO: would this interfere with non-blocking nature of this VM? */ + if (errno == EINTR) continue; + #endif + return -1; + } + + ptr += wr; + len -= wr; + } + + return 0; +} + +static int write_log (mio_t* mio, int fd, const mio_bch_t* ptr, mio_oow_t len) +{ + xtn_t* xtn = GET_XTN(mio); + + while (len > 0) + { + if (xtn->log.out.len > 0) + { + mio_oow_t rcapa, cplen; + + rcapa = MIO_COUNTOF(xtn->log.out.buf) - xtn->log.out.len; + cplen = (len >= rcapa)? rcapa: len; + + MIO_MEMCPY (&xtn->log.out.buf[xtn->log.out.len], ptr, cplen); + xtn->log.out.len += cplen; + ptr += cplen; + len -= cplen; + + if (xtn->log.out.len >= MIO_COUNTOF(xtn->log.out.buf)) + { + int n; + n = write_all(fd, xtn->log.out.buf, xtn->log.out.len); + xtn->log.out.len = 0; + if (n <= -1) return -1; + } + } + else + { + mio_oow_t rcapa; + + rcapa = MIO_COUNTOF(xtn->log.out.buf); + if (len >= rcapa) + { + if (write_all(fd, ptr, rcapa) <= -1) return -1; + ptr += rcapa; + len -= rcapa; + } + else + { + MIO_MEMCPY (xtn->log.out.buf, ptr, len); + xtn->log.out.len += len; + ptr += len; + len -= len; + + } + } + } + + return 0; +} + +static void flush_log (mio_t* mio, int fd) +{ + xtn_t* xtn = GET_XTN(mio); + if (xtn->log.out.len > 0) + { + write_all (fd, xtn->log.out.buf, xtn->log.out.len); + xtn->log.out.len = 0; + } +} + +void mio_sys_writelog (mio_t* mio, mio_bitmask_t mask, const mio_ooch_t* msg, mio_oow_t len) +{ + xtn_t* xtn = GET_XTN(mio); + mio_bch_t buf[256]; + mio_oow_t ucslen, bcslen, msgidx; + int n, logfd; + + if (mask & MIO_LOG_STDERR) + { + /* the messages that go to STDERR don't get masked out */ + logfd = 2; + } + else + { +#if 0 + if (!(xtn->log.mask & mask & ~MIO_LOG_ALL_LEVELS)) return; /* check log types */ + if (!(xtn->log.mask & mask & ~MIO_LOG_ALL_TYPES)) return; /* check log levels */ +#endif + + if (mask & MIO_LOG_STDOUT) logfd = 1; + else + { + logfd = xtn->log.fd; + if (logfd <= -1) return; + } + } + +/* TODO: beautify the log message. + * do classification based on mask. */ + if (!(mask & (MIO_LOG_STDOUT | MIO_LOG_STDERR))) + { + time_t now; + char ts[32]; + size_t tslen; + struct tm tm, *tmp; + + now = time(MIO_NULL); + #if defined(_WIN32) + tmp = localtime(&now); + tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp); + if (tslen == 0) + { + tslen = sprintf(ts, "%04d-%02d-%02d %02d:%02d:%02d ", tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + } + #elif defined(__OS2__) + #if defined(__WATCOMC__) + tmp = _localtime(&now, &tm); + #else + tmp = localtime(&now); + #endif + + #if defined(__BORLANDC__) + /* the borland compiler doesn't handle %z properly - it showed 00 all the time */ + tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %Z ", tmp); + #else + tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp); + #endif + if (tslen == 0) + { + tslen = sprintf(ts, "%04d-%02d-%02d %02d:%02d:%02d ", tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + } + + #elif defined(__DOS__) + tmp = localtime(&now); + /* since i know that %z/%Z is not available in strftime, i switch to sprintf immediately */ + tslen = sprintf(ts, "%04d-%02d-%02d %02d:%02d:%02d ", tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + #else + #if defined(HAVE_LOCALTIME_R) + tmp = localtime_r(&now, &tm); + #else + tmp = localtime(&now); + #endif + + #if defined(HAVE_STRFTIME_SMALL_Z) + tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %z ", tmp); + #else + tslen = strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S %Z ", tmp); + #endif + if (tslen == 0) + { + tslen = sprintf(ts, "%04d-%02d-%02d %02d:%02d:%02d ", tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + } + #endif + write_log (mio, logfd, ts, tslen); + } + + if (logfd == xtn->log.fd && (xtn->log.fd_flag & LOGFD_TTY)) + { + if (mask & MIO_LOG_FATAL) write_log (mio, logfd, "\x1B[1;31m", 7); + else if (mask & MIO_LOG_ERROR) write_log (mio, logfd, "\x1B[1;32m", 7); + else if (mask & MIO_LOG_WARN) write_log (mio, logfd, "\x1B[1;33m", 7); + } + +#if defined(MIO_OOCH_IS_UCH) + msgidx = 0; + while (len > 0) + { + ucslen = len; + bcslen = MIO_COUNTOF(buf); + + n = mio_convootobchars(mio, &msg[msgidx], &ucslen, buf, &bcslen); + if (n == 0 || n == -2) + { + /* n = 0: + * converted all successfully + * n == -2: + * buffer not sufficient. not all got converted yet. + * write what have been converted this round. */ + + MIO_ASSERT (mio, ucslen > 0); /* if this fails, the buffer size must be increased */ + + /* attempt to write all converted characters */ + if (write_log(mio, logfd, buf, bcslen) <= -1) break; + + if (n == 0) break; + else + { + msgidx += ucslen; + len -= ucslen; + } + } + else if (n <= -1) + { + /* conversion error */ + break; + } + } +#else + write_log (mio, logfd, msg, len); +#endif + + if (logfd == xtn->log.fd && (xtn->log.fd_flag & LOGFD_TTY)) + { + if (mask & (MIO_LOG_FATAL | MIO_LOG_ERROR | MIO_LOG_WARN)) write_log (mio, logfd, "\x1B[0m", 4); + } + + flush_log (mio, logfd); +}