r3939 - in trunk/birnet: . tests
- From: timj svn gnome org
- To: svn-commits-list gnome org
- Subject: r3939 - in trunk/birnet: . tests
- Date: Fri, 6 Oct 2006 17:53:55 -0400 (EDT)
Author: timj
Date: 2006-10-06 17:53:52 -0400 (Fri, 06 Oct 2006)
New Revision: 3939
Added:
trunk/birnet/birnetcdefs.h
trunk/birnet/birnetcpu.cc
trunk/birnet/birnetcpu.hh
Removed:
trunk/birnet/birnetcore.c
trunk/birnet/birnetcore.h
trunk/birnet/birnetcpu.c
trunk/birnet/birnetcpu.h
trunk/birnet/birnetutils.cc
trunk/birnet/birnetutils.hh
Modified:
trunk/birnet/ChangeLog
trunk/birnet/Makefile.am
trunk/birnet/birnet-zintern.cc
trunk/birnet/birnet.hh
trunk/birnet/birnetmsg.cc
trunk/birnet/birnetmsg.hh
trunk/birnet/birnettests.h
trunk/birnet/birnetthread.c
trunk/birnet/birnetthread.h
trunk/birnet/birnetutilsxx.cc
trunk/birnet/birnetutilsxx.hh
trunk/birnet/configure.inc
trunk/birnet/tests/infotest.cc
Log:
Fri Oct 6 23:26:10 2006 Tim Janik <timj gtk org>
* birnetcdefs.h: new header file to contain (or include) all definitions
and declarations that are useful for C only programs. while Birnet is not
to support *any* C symbol at all, using common structure definitions
helps in wrapping certain features for C programs.
* birnetcpu.hh, birnetcpu.cc: renamed and moved from .h and .c.
* birnetutilsxx.hh, birnetutilsxx.cc: use birnetcdefs.h definitions.
provided init functionality. added raise_sigtrap() and BREAKPOINT()
implementations.
* birnetutilsxx.hh, birnetutilsxx.cc: merged everything from
birnetutils.hh and birnetutils.cc into these files.
* birnet-zintern.cc:
* birnettests.h: namespace fixups.
* configure.inc: detect windows operating system.
Modified: trunk/birnet/ChangeLog
===================================================================
--- trunk/birnet/ChangeLog 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/ChangeLog 2006-10-06 21:53:52 UTC (rev 3939)
@@ -1,3 +1,24 @@
+Fri Oct 6 23:26:10 2006 Tim Janik <timj gtk org>
+
+ * birnetcdefs.h: new header file to contain (or include) all definitions
+ and declarations that are useful for C only programs. while Birnet is not
+ to support *any* C symbol at all, using common structure definitions
+ helps in wrapping certain features for C programs.
+
+ * birnetcpu.hh, birnetcpu.cc: renamed and moved from .h and .c.
+
+ * birnetutilsxx.hh, birnetutilsxx.cc: use birnetcdefs.h definitions.
+ provided init functionality. added raise_sigtrap() and BREAKPOINT()
+ implementations.
+
+ * birnetutilsxx.hh, birnetutilsxx.cc: merged everything from
+ birnetutils.hh and birnetutils.cc into these files.
+
+ * birnet-zintern.cc:
+ * birnettests.h: namespace fixups.
+
+ * configure.inc: detect windows operating system.
+
Fri Oct 6 18:53:30 2006 Tim Janik <timj gtk org>
* birnet.hh: renamed from birnet.h.
Modified: trunk/birnet/Makefile.am
===================================================================
--- trunk/birnet/Makefile.am 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/Makefile.am 2006-10-06 21:53:52 UTC (rev 3939)
@@ -10,24 +10,20 @@
birnet_headers = $(strip \
birnet.hh \
- birnetcore.h \
- birnetcpu.h \
+ birnetcpu.hh \
birnetmsg.hh \
birnetsignal.hh \
birnettests.h \
birnetthread.h \
birnetthreadxx.hh \
- birnetutils.hh \
birnetutilsxx.hh \
)
birnet_sources = $(strip \
- birnetcore.c \
- birnetcpu.c \
+ birnetcpu.cc \
birnetmsg.cc \
birnetsignal.cc \
birnetthread.c \
birnetthreadxx.cc \
- birnetutils.cc \
birnetutilsxx.cc \
)
birnet_private_headers = $(strip \
@@ -102,6 +98,7 @@
&& echo " BIRNET_MICRO_VERSION >= (micro)))" >> xgen-$(@F) \
&& echo "" >> xgen-$(@F) \
&& echo "/* configure results */" >> xgen-$(@F) \
+ && echo "#define BIRNET_OS_ BIRNET_OS@ (1)" >> xgen-$(@F) \
&& echo "#define BIRNET_SIZEOF_SYS_TYPESH_UINT (@BIRNET_SIZEOF_SYS_TYPESH_UINT@)" >> xgen-$(@F) \
&& echo "#define BIRNET_SIZEOF_PTH_MUTEX_T (@BIRNET_SIZEOF_PTH_MUTEX_T@)" >> xgen-$(@F) \
&& echo "#define BIRNET_SIZEOF_PTH_COND_T (@BIRNET_SIZEOF_PTH_COND_T@)" >> xgen-$(@F) \
Modified: trunk/birnet/birnet-zintern.cc
===================================================================
--- trunk/birnet/birnet-zintern.cc 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnet-zintern.cc 2006-10-06 21:53:52 UTC (rev 3939)
@@ -21,6 +21,8 @@
#include <errno.h>
#include <zlib.h>
+namespace Birnet {
+
static gboolean use_compression = FALSE;
static gboolean use_base_name = FALSE;
@@ -183,17 +185,17 @@
return arg != NULL;
}
-int
+extern "C" int
main (gint argc,
gchar *argv[])
{
GSList *plist = NULL;
- BirnetInitValue ivalues[] = {
+ InitValue ivalues[] = {
{ "stand-alone", "true" },
{ NULL }
};
- birnet_init_extended (&argc, &argv, NULL, ivalues);
+ birnet_init (&argc, &argv, NULL, ivalues);
for (int i = 1; i < argc; i++)
{
@@ -231,3 +233,5 @@
return 0;
}
+
+} // Birnet
Modified: trunk/birnet/birnet.hh
===================================================================
--- trunk/birnet/birnet.hh 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnet.hh 2006-10-06 21:53:52 UTC (rev 3939)
@@ -20,10 +20,8 @@
#define __BIRNET_H__
#include <birnet/birnetconfig.h>
-#include <birnet/birnetcore.h>
-#include <birnet/birnetcpu.h>
+#include <birnet/birnetcpu.hh>
-#include <birnet/birnetutils.hh>
#include <birnet/birnetmsg.hh>
#include <birnet/birnetthread.h>
Copied: trunk/birnet/birnetcdefs.h (from rev 3937, trunk/birnet/birnetcore.h)
===================================================================
--- trunk/birnet/birnetcore.h 2006-10-06 16:55:46 UTC (rev 3937)
+++ trunk/birnet/birnetcdefs.h 2006-10-06 21:53:52 UTC (rev 3939)
@@ -0,0 +1,196 @@
+/* BirnetCDefs - C compatible definitions
+ * Copyright (C) 2006 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __BIRNET_CDEFS_H__
+#define __BIRNET_CDEFS_H__
+
+#include <stdbool.h>
+#include <stddef.h> /* NULL */
+#include <sys/types.h> /* uint, ssize */
+#include <birnet/birnetconfig.h>
+
+BIRNET_EXTERN_C_BEGIN();
+
+/* --- standard macros --- */
+#define BIRNET_ABS(a) ((a) > -(a) ? (a) : -(a))
+#define BIRNET_MIN(a,b) ((a) <= (b) ? (a) : (b))
+#define BIRNET_MAX(a,b) ((a) >= (b) ? (a) : (b))
+#define BIRNET_CLAMP(v,mi,ma) ((v) < (mi) ? (mi) : ((v) > (ma) ? (ma) : (v)))
+#ifdef _BIRNET_SOURCE_EXTENSIONS
+#undef ABS
+#define ABS BIRNET_ABS
+#undef MIN
+#define MIN BIRNET_MIN
+#undef MAX
+#define MAX BIRNET_MAX
+#undef CLAMP
+#define CLAMP BIRNET_CLAMP
+#undef STRFUNC
+#define STRFUNC G_STRFUNC
+#endif /* _BIRNET_SOURCE_EXTENSIONS */
+
+/* --- likelyness hinting --- */
+#define BIRNET__BOOL(expr) __extension__ ({ bool _birnet__bool; if (expr) _birnet__bool = 1; else _birnet__bool = 0; _birnet__bool; })
+#define BIRNET_ISLIKELY(expr) __builtin_expect (BIRNET__BOOL (expr), 1)
+#define BIRNET_UNLIKELY(expr) __builtin_expect (BIRNET__BOOL (expr), 0)
+#define BIRNET_LIKELY BIRNET_ISLIKELY
+
+/* --- assertions and runtime errors --- */
+#define BIRNET_RETURN_IF_FAIL(e) do { if (BIRNET_ISLIKELY (e)) break; BIRNET__RUNTIME_PROBLEM ('R', BIRNET_LOG_DOMAIN, __FILE__, __LINE__, BIRNET_SIMPLE_FUNCTION, "%s", #e); return; } while (0)
+#define BIRNET_RETURN_VAL_IF_FAIL(e,v) do { if (BIRNET_ISLIKELY (e)) break; BIRNET__RUNTIME_PROBLEM ('R', BIRNET_LOG_DOMAIN, __FILE__, __LINE__, BIRNET_SIMPLE_FUNCTION, "%s", #e); return v; } while (0)
+#define BIRNET_ASSERT(e) do { if (BIRNET_ISLIKELY (e)) break; BIRNET__RUNTIME_PROBLEM ('A', BIRNET_LOG_DOMAIN, __FILE__, __LINE__, BIRNET_SIMPLE_FUNCTION, "%s", #e); _exit(127); } while (0)
+#define BIRNET_ASSERT_NOT_REACHED() do { BIRNET__RUNTIME_PROBLEM ('N', BIRNET_LOG_DOMAIN, __FILE__, __LINE__, BIRNET_SIMPLE_FUNCTION, NULL); } while (0)
+#define BIRNET_WARNING(...) do { BIRNET__RUNTIME_PROBLEM ('W', BIRNET_LOG_DOMAIN, __FILE__, __LINE__, BIRNET_SIMPLE_FUNCTION, __VA_ARGS__); } while (0)
+#define BIRNET_ERROR(...) do { BIRNET__RUNTIME_PROBLEM ('E', BIRNET_LOG_DOMAIN, __FILE__, __LINE__, BIRNET_SIMPLE_FUNCTION, __VA_ARGS__); _exit(127); } while (0)
+/* the above macros rely on a problem handler macro: */
+// BIRNET__RUNTIME_PROBLEM(ErrorWarningReturnAssertNotreach,domain,file,line,funcname,exprformat,...); // noreturn cases: 'E', 'A', 'N'
+
+/* --- convenient aliases --- */
+#ifdef _BIRNET_SOURCE_EXTENSIONS
+#define ISLIKELY BIRNET_ISLIKELY
+#define UNLIKELY BIRNET_UNLIKELY
+#define LIKELY BIRNET_LIKELY
+#define RETURN_IF_FAIL BIRNET_RETURN_IF_FAIL
+#define RETURN_VAL_IF_FAIL BIRNET_RETURN_VAL_IF_FAIL
+#define ASSERT_NOT_REACHED BIRNET_ASSERT_NOT_REACHED
+#define ASSERT BIRNET_ASSERT
+#define WARNING BIRNET_WARNING
+#define ERROR BIRNET_ERROR
+#endif /* _BIRNET_SOURCE_EXTENSIONS */
+
+/* --- preprocessor pasting --- */
+#define BIRNET_CPP_PASTE4i(a,b,c,d) a ## b ## c ## d /* twofold indirection is required to expand macros like __LINE__ */
+#define BIRNET_CPP_PASTE4(a,b,c,d) BIRNET_CPP_PASTE4i (a,b,c,d)
+#define BIRNET_CPP_PASTE3i(a,b,c) a ## b ## c /* twofold indirection is required to expand macros like __LINE__ */
+#define BIRNET_CPP_PASTE3(a,b,c) BIRNET_CPP_PASTE3i (a,b,c)
+#define BIRNET_CPP_PASTE2i(a,b) a ## b /* twofold indirection is required to expand macros like __LINE__ */
+#define BIRNET_CPP_PASTE2(a,b) BIRNET_CPP_PASTE2i (a,b)
+#define BIRNET_STATIC_ASSERT_NAMED(expr,asname) typedef struct { char asname[(expr) ? 1 : -1]; } BIRNET_CPP_PASTE2 (Birnet_StaticAssertion_LINE, __LINE__)
+#define BIRNET_STATIC_ASSERT(expr) BIRNET_STATIC_ASSERT_NAMED (expr, compile_time_assertion_failed)
+
+/* --- attributes --- */
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+#define BIRNET_PRETTY_FUNCTION (__PRETTY_FUNCTION__)
+#define BIRNET_PURE __attribute__ ((__pure__))
+#define BIRNET_MALLOC __attribute__ ((__malloc__))
+#define BIRNET_PRINTF(format_idx, arg_idx) __attribute__ ((__format__ (__printf__, format_idx, arg_idx)))
+#define BIRNET_SCANF(format_idx, arg_idx) __attribute__ ((__format__ (__scanf__, format_idx, arg_idx)))
+#define BIRNET_FORMAT(arg_idx) __attribute__ ((__format_arg__ (arg_idx)))
+#define BIRNET_NORETURN __attribute__ ((__noreturn__))
+#define BIRNET_CONST __attribute__ ((__const__))
+#define BIRNET_UNUSED __attribute__ ((__unused__))
+#define BIRNET_NO_INSTRUMENT __attribute__ ((__no_instrument_function__))
+#define BIRNET_DEPRECATED __attribute__ ((__deprecated__))
+#define BIRNET_ALWAYS_INLINE __attribute__ ((always_inline))
+#define BIRNET_NEVER_INLINE __attribute__ ((noinline))
+#define BIRNET_CONSTRUCTOR __attribute__ ((constructor,used)) /* gcc-3.3 also needs "used" to emit code */
+#else /* !__GNUC__ */
+#define BIRNET_PRETTY_FUNCTION ("<unknown>")
+#define BIRNET_PURE
+#define BIRNET_MALLOC
+#define BIRNET_PRINTF(format_idx, arg_idx)
+#define BIRNET_SCANF(format_idx, arg_idx)
+#define BIRNET_FORMAT(arg_idx)
+#define BIRNET_NORETURN
+#define BIRNET_CONST
+#define BIRNET_UNUSED
+#define BIRNET_NO_INSTRUMENT
+#define BIRNET_DEPRECATED
+#define BIRNET_ALWAYS_INLINE
+#define BIRNET_NEVER_INLINE
+#define BIRNET_CONSTRUCTOR
+#error Failed to detect a recent GCC version (>= 3.3)
+#endif /* !__GNUC__ */
+#ifdef __cplusplus
+#define BIRNET_SIMPLE_FUNCTION (__func__)
+#else
+#define BIRNET_SIMPLE_FUNCTION BIRNET_PRETTY_FUNCTION
+#endif
+
+/* --- provide canonical integer types --- */
+#if BIRNET_SIZEOF_SYS_TYPESH_UINT == 0
+typedef unsigned int uint; /* for systems that don't define uint in types.h */
+#else
+BIRNET_STATIC_ASSERT (BIRNET_SIZEOF_SYS_TYPESH_UINT == 4);
+#endif
+BIRNET_STATIC_ASSERT (sizeof (uint) == 4);
+typedef unsigned int BirnetUInt8 __attribute__ ((__mode__ (__QI__)));
+typedef unsigned int BirnetUInt16 __attribute__ ((__mode__ (__HI__)));
+typedef unsigned int BirnetUInt32 __attribute__ ((__mode__ (__SI__)));
+typedef unsigned int BirnetUInt64 __attribute__ ((__mode__ (__DI__)));
+// provided by birnetcdefs.h: uint;
+BIRNET_STATIC_ASSERT (sizeof (BirnetUInt8) == 1);
+BIRNET_STATIC_ASSERT (sizeof (BirnetUInt16) == 2);
+BIRNET_STATIC_ASSERT (sizeof (BirnetUInt32) == 4);
+BIRNET_STATIC_ASSERT (sizeof (BirnetUInt64) == 8);
+typedef signed int BirnetInt8 __attribute__ ((__mode__ (__QI__)));
+typedef signed int BirnetInt16 __attribute__ ((__mode__ (__HI__)));
+typedef signed int BirnetInt32 __attribute__ ((__mode__ (__SI__)));
+typedef signed int BirnetInt64 __attribute__ ((__mode__ (__DI__)));
+// provided by compiler int;
+BIRNET_STATIC_ASSERT (sizeof (BirnetInt8) == 1);
+BIRNET_STATIC_ASSERT (sizeof (BirnetInt16) == 2);
+BIRNET_STATIC_ASSERT (sizeof (BirnetInt32) == 4);
+BIRNET_STATIC_ASSERT (sizeof (BirnetInt64) == 8);
+typedef BirnetUInt32 BirnetUnichar;
+BIRNET_STATIC_ASSERT (sizeof (BirnetUnichar) == 4);
+
+
+/* --- path handling --- */
+#ifdef BIRNET_OS_WIN32
+#define BIRNET_DIR_SEPARATOR '\\'
+#define BIRNET_DIR_SEPARATOR_S "\\"
+#define BIRNET_SEARCHPATH_SEPARATOR ';'
+#define BIRNET_SEARCHPATH_SEPARATOR_S ";"
+#else /* !BIRNET_OS_WIN32 */
+#define BIRNET_DIR_SEPARATOR '/'
+#define BIRNET_DIR_SEPARATOR_S "/"
+#define BIRNET_SEARCHPATH_SEPARATOR ':'
+#define BIRNET_SEARCHPATH_SEPARATOR_S ":"
+#endif /* !BIRNET_OS_WIN32 */
+#define BIRNET_IS_DIR_SEPARATOR(c) ((c) == BIRNET_DIR_SEPARATOR)
+#define BIRNET_IS_SEARCHPATH_SEPARATOR(c) ((c) == BIRNET_SEARCHPATH_SEPARATOR)
+
+/* --- initialization --- */
+typedef struct {
+ bool stand_alone; /* "stand-alone": no rcfiles, boot scripts, etc. */
+} BirnetInitSettings;
+
+typedef struct {
+ const char *value_name; /* value list ends with value_name == NULL */
+ const char *value_string;
+ long double value_num; /* valid if value_string == NULL */
+} BirnetInitValue;
+
+/* --- CPU info --- */
+typedef struct {
+ /* architecture name */
+ const char *machine;
+ /* CPU Vendor ID */
+ const char *cpu_vendor;
+ /* CPU features on X86 */
+ uint x86_fpu : 1, x86_tsc : 1, x86_htt : 1;
+ uint x86_mmx : 1, x86_mmxext : 1, x86_3dnow : 1, x86_3dnowext : 1;
+ uint x86_sse : 1, x86_sse2 : 1, x86_sse3 : 1, x86_ssesys : 1;
+} BirnetCPUInfo;
+
+BIRNET_EXTERN_C_END();
+
+#endif /* __BIRNET_CDEFS_H__ */
+
+/* vim:set ts=8 sts=2 sw=2: */
Deleted: trunk/birnet/birnetcore.c
===================================================================
--- trunk/birnet/birnetcore.c 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetcore.c 2006-10-06 21:53:52 UTC (rev 3939)
@@ -1,61 +0,0 @@
-/* Birnet
- * Copyright (C) 2006 Tim Janik
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#include "birnetcore.h"
-#include <stdlib.h>
-
-void
-birnet_init (int *argcp,
- char ***argvp,
- const char *app_name)
-{
- birnet_init_extended (argcp, argvp, app_name, NULL);
-}
-
-bool
-birnet_init_value_bool (BirnetInitValue *value)
-{
- if (value->value_string)
- switch (value->value_string[0])
- {
- case 0:
- case '0': case 'f': case 'F':
- case 'n': case 'N': /* false assigments */
- return FALSE;
- default:
- return TRUE;
- }
- else
- return ABS (value->value_num) >= 0.5;
-}
-
-double
-birnet_init_value_double (BirnetInitValue *value)
-{
- if (value->value_string)
- return g_strtod (value->value_string, NULL);
- return value->value_num;
-}
-
-gint64
-birnet_init_value_int (BirnetInitValue *value)
-{
- if (value->value_string)
- return strtoll (value->value_string, NULL, 0);
- return value->value_num + 0.5;
-}
Deleted: trunk/birnet/birnetcore.h
===================================================================
--- trunk/birnet/birnetcore.h 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetcore.h 2006-10-06 21:53:52 UTC (rev 3939)
@@ -1,193 +0,0 @@
-/* Birnet
- * Copyright (C) 2006 Tim Janik
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#ifndef __BIRNET_CORE_H__
-#define __BIRNET_CORE_H__
-
-#include <stdbool.h>
-#include <stddef.h> /* NULL */
-#include <sys/types.h> /* uint, ssize */
-#include <glib.h>
-#include <birnet/birnetconfig.h>
-
-BIRNET_EXTERN_C_BEGIN();
-
-/* --- standard macros --- */
-#define BIRNET_ABS(a) ((a) > -(a) ? (a) : -(a))
-#define BIRNET_MIN(a,b) ((a) <= (b) ? (a) : (b))
-#define BIRNET_MAX(a,b) ((a) >= (b) ? (a) : (b))
-#define BIRNET_CLAMP(v,mi,ma) ((v) < (mi) ? (mi) : ((v) > (ma) ? (ma) : (v)))
-#ifdef _BIRNET_SOURCE_EXTENSIONS
-#undef ABS
-#define ABS BIRNET_ABS
-#undef MIN
-#define MIN BIRNET_MIN
-#undef MAX
-#define MAX BIRNET_MAX
-#undef CLAMP
-#define CLAMP BIRNET_CLAMP
-#undef STRFUNC
-#define STRFUNC G_STRFUNC
-#endif /* _BIRNET_SOURCE_EXTENSIONS */
-
-/* --- reliable assert --- */
-#define BIRNET_LIKELY G_LIKELY
-#define BIRNET_ISLIKELY G_LIKELY
-#define BIRNET_UNLIKELY G_UNLIKELY
-#define BIRNET_RETURN_IF_FAIL(e) do { if G_LIKELY (e) {} else { g_return_if_fail_warning (G_LOG_DOMAIN, __PRETTY_FUNCTION__, #e); return; } } while (0)
-#define BIRNET_RETURN_VAL_IF_FAIL(e,v) do { if G_LIKELY (e) {} else { g_return_if_fail_warning (G_LOG_DOMAIN, __PRETTY_FUNCTION__, #e); return v; } } while (0)
-#define BIRNET_ASSERT_NOT_REACHED() do { g_assert_warning (G_LOG_DOMAIN, __FILE__, __LINE__, __PRETTY_FUNCTION__, NULL); } while (0)
-#define BIRNET_ASSERT(expr) do { /* never disabled */ \
- if G_LIKELY (expr) {} else \
- g_assert_warning (G_LOG_DOMAIN, __FILE__, __LINE__, \
- __PRETTY_FUNCTION__, #expr); \
-} while (0)
-/* convenient aliases */
-#ifdef _BIRNET_SOURCE_EXTENSIONS
-#define RETURN_IF_FAIL BIRNET_RETURN_IF_FAIL
-#define RETURN_VAL_IF_FAIL BIRNET_RETURN_VAL_IF_FAIL
-#define ASSERT_NOT_REACHED BIRNET_ASSERT_NOT_REACHED
-#define ASSERT BIRNET_ASSERT
-#define LIKELY BIRNET_LIKELY
-#define ISLIKELY BIRNET_ISLIKELY
-#define UNLIKELY BIRNET_UNLIKELY
-#endif /* _BIRNET_SOURCE_EXTENSIONS */
-
-/* --- compile time assertions --- */
-#define BIRNET_CPP_PASTE4i(a,b,c,d) a ## b ## c ## d /* twofold indirection is required to expand macros like __LINE__ */
-#define BIRNET_CPP_PASTE4(a,b,c,d) BIRNET_CPP_PASTE4i (a,b,c,d)
-#define BIRNET_CPP_PASTE3i(a,b,c) a ## b ## c /* twofold indirection is required to expand macros like __LINE__ */
-#define BIRNET_CPP_PASTE3(a,b,c) BIRNET_CPP_PASTE3i (a,b,c)
-#define BIRNET_CPP_PASTE2i(a,b) a ## b /* twofold indirection is required to expand macros like __LINE__ */
-#define BIRNET_CPP_PASTE2(a,b) BIRNET_CPP_PASTE2i (a,b)
-#define BIRNET_STATIC_ASSERT_NAMED(expr,asname) typedef struct { char asname[(expr) ? 1 : -1]; } BIRNET_CPP_PASTE2 (Birnet_StaticAssertion_LINE, __LINE__)
-#define BIRNET_STATIC_ASSERT(expr) BIRNET_STATIC_ASSERT_NAMED (expr, compile_time_assertion_failed)
-
-/* --- common type definitions --- */
-typedef unsigned int BirnetUInt8 __attribute__ ((__mode__ (__QI__)));
-typedef unsigned int BirnetUInt16 __attribute__ ((__mode__ (__HI__)));
-typedef unsigned int BirnetUInt32 __attribute__ ((__mode__ (__SI__)));
-typedef unsigned int BirnetUInt64 __attribute__ ((__mode__ (__DI__)));
-typedef BirnetUInt32 BirnetUInt;
-BIRNET_STATIC_ASSERT (sizeof (BirnetUInt8) == 1);
-BIRNET_STATIC_ASSERT (sizeof (BirnetUInt16) == 2);
-BIRNET_STATIC_ASSERT (sizeof (BirnetUInt32) == 4);
-BIRNET_STATIC_ASSERT (sizeof (BirnetUInt64) == 8);
-typedef signed int BirnetInt8 __attribute__ ((__mode__ (__QI__)));
-typedef signed int BirnetInt16 __attribute__ ((__mode__ (__HI__)));
-typedef signed int BirnetInt32 __attribute__ ((__mode__ (__SI__)));
-typedef signed int BirnetInt64 __attribute__ ((__mode__ (__DI__)));
-typedef BirnetInt32 BirnetInt;
-BIRNET_STATIC_ASSERT (sizeof (BirnetInt8) == 1);
-BIRNET_STATIC_ASSERT (sizeof (BirnetInt16) == 2);
-BIRNET_STATIC_ASSERT (sizeof (BirnetInt32) == 4);
-BIRNET_STATIC_ASSERT (sizeof (BirnetInt64) == 8);
-typedef BirnetUInt32 BirnetUniChar;
-
-/* --- attributes --- */
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
-#define BIRNET_PRETTY_FUNCTION (__PRETTY_FUNCTION__)
-#define BIRNET_PURE __attribute__ ((__pure__))
-#define BIRNET_MALLOC __attribute__ ((__malloc__))
-#define BIRNET_PRINTF(format_idx, arg_idx) __attribute__ ((__format__ (__printf__, format_idx, arg_idx)))
-#define BIRNET_SCANF(format_idx, arg_idx) __attribute__ ((__format__ (__scanf__, format_idx, arg_idx)))
-#define BIRNET_FORMAT(arg_idx) __attribute__ ((__format_arg__ (arg_idx)))
-#define BIRNET_NORETURN __attribute__ ((__noreturn__))
-#define BIRNET_CONST __attribute__ ((__const__))
-#define BIRNET_UNUSED __attribute__ ((__unused__))
-#define BIRNET_NO_INSTRUMENT __attribute__ ((__no_instrument_function__))
-#define BIRNET_DEPRECATED __attribute__ ((__deprecated__))
-#define BIRNET_ALWAYS_INLINE __attribute__ ((always_inline))
-#define BIRNET_NEVER_INLINE __attribute__ ((noinline))
-#define BIRNET_CONSTRUCTOR __attribute__ ((constructor,used)) /* gcc-3.3 also needs "used" */
-#else /* !__GNUC__ */
-#define BIRNET_PRETTY_FUNCTION (__func__)
-#define BIRNET_PURE
-#define BIRNET_MALLOC
-#define BIRNET_PRINTF(format_idx, arg_idx)
-#define BIRNET_SCANF(format_idx, arg_idx)
-#define BIRNET_FORMAT(arg_idx)
-#define BIRNET_NORETURN
-#define BIRNET_CONST
-#define BIRNET_UNUSED
-#define BIRNET_NO_INSTRUMENT
-#define BIRNET_DEPRECATED
-#define BIRNET_ALWAYS_INLINE
-#define BIRNET_NEVER_INLINE
-#define BIRNET_CONSTRUCTOR
-#error Failed to detect a recent GCC version (>= 3.3)
-#endif /* !__GNUC__ */
-
-/* --- convenient type shorthands --- */
-#ifdef _BIRNET_SOURCE_EXTENSIONS
-#if BIRNET_SIZEOF_SYS_TYPESH_UINT == 0
-typedef unsigned int uint; /* for systems that don't define uint in types.h */
-#else
-BIRNET_STATIC_ASSERT (BIRNET_SIZEOF_SYS_TYPESH_UINT == 4);
-#endif
-BIRNET_STATIC_ASSERT (sizeof (uint) == 4);
-typedef BirnetUInt8 uint8;
-typedef BirnetUInt16 uint16;
-typedef BirnetUInt32 uint32;
-typedef BirnetUInt64 uint64;
-typedef BirnetInt8 int8;
-typedef BirnetInt16 int16;
-typedef BirnetInt32 int32;
-typedef BirnetInt64 int64;
-typedef BirnetUniChar unichar;
-#endif /* _BIRNET_SOURCE_EXTENSIONS */
-
-/* --- path handling --- */
-#define BIRNET_DIR_SEPARATOR G_DIR_SEPARATOR /* '/' */
-#define BIRNET_DIR_SEPARATOR_S G_DIR_SEPARATOR_S /* "/" */
-#define BIRNET_IS_DIR_SEPARATOR(c) G_IS_DIR_SEPARATOR(c) /* (c) == G_DIR_SEPARATOR */
-#define BIRNET_SEARCHPATH_SEPARATOR G_SEARCHPATH_SEPARATOR /* ':' */
-#define BIRNET_SEARCHPATH_SEPARATOR_S G_SEARCHPATH_SEPARATOR_S /* ":" */
-#ifdef G_OS_WIN32
-#define BIRNET_IS_SEARCHPATH_SEPARATOR(c) ((c) == G_SEARCHPATH_SEPARATOR /* ';' */)
-#else /* !G_OS_WIN32 */
-#define BIRNET_IS_SEARCHPATH_SEPARATOR(c) ((c) == G_SEARCHPATH_SEPARATOR || (c) == ';')
-#endif
-
-/* --- birnet initialization --- */
-typedef struct
-{
- const char *value_name; /* value list ends with value_name == NULL */
- const char *value_string;
- long double value_num; /* valid if value_string == NULL */
-} BirnetInitValue;
-void birnet_init_extended (int *argcp,
- char ***argvp,
- const char *app_name,
- BirnetInitValue bivalues[]); /* in birnetutilsxx.cc */
-void birnet_init (int *argcp,
- char ***argvp,
- const char *app_name);
-bool birnet_init_value_bool (BirnetInitValue *value);
-double birnet_init_value_double (BirnetInitValue *value);
-gint64 birnet_init_value_int (BirnetInitValue *value);
-typedef struct {
- bool stand_alone; /* "stand-alone": no rcfiles, boot scripts, etc. */
-} BirnetInitSettings;
-extern BirnetInitSettings *birnet_init_settings;
-
-BIRNET_EXTERN_C_END();
-
-#endif /* __BIRNET_CORE_H__ */
-
-/* vim:set ts=8 sts=2 sw=2: */
Deleted: trunk/birnet/birnetcpu.c
===================================================================
--- trunk/birnet/birnetcpu.c 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetcpu.c 2006-10-06 21:53:52 UTC (rev 3939)
@@ -1,300 +0,0 @@
-/* BirnetCPU
- * Copyright (C) 2006 Tim Janik
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#include "birnetcpu.h"
-#include <setjmp.h>
-#include <signal.h>
-#include <string.h>
-
-/* figure architecture name from compiler */
-static const char*
-get_arch_name (void)
-{
-#if defined __alpha__
- return "Alpha";
-#elif defined __frv__
- return "frv";
-#elif defined __s390__
- return "s390";
-#elif defined __m32c__
- return "m32c";
-#elif defined sparc
- return "Sparc";
-#elif defined __m32r__
- return "m32r";
-#elif defined __x86_64__ || defined __amd64__
- return "AMD64";
-#elif defined __ia64__
- return "Intel Itanium";
-#elif defined __m68k__
- return "mc68000";
-#elif defined __powerpc__ || defined PPC || defined powerpc || defined __PPC__
- return "PPC";
-#elif defined __arc__
- return "arc";
-#elif defined __arm__
- return "Arm";
-#elif defined __mips__ || defined mips
- return "Mips";
-#elif defined __tune_i686__ || defined __i686__
- return "i686";
-#elif defined __tune_i586__ || defined __i586__
- return "i586";
-#elif defined __tune_i486__ || defined __i486__
- return "i486";
-#elif defined i386 || defined __i386__
- return "i386";
-#else
- return "unknown-arch";
-#endif
-}
-
-/* --- X86 detection via CPUID --- */
-#if defined __i386__
-# define x86_has_cpuid() ({ \
- unsigned int __eax, __ecx; \
- __asm__ __volatile__ \
- ( \
- /* copy EFLAGS into eax and ecx */ \
- "pushf ; pop %0 ; mov %0, %1 \n\t" \
- /* toggle the ID bit and store back to EFLAGS */ \
- "xor $0x200000, %0 ; push %0 ; popf \n\t" \
- /* read back EFLAGS with possibly modified ID bit */ \
- "pushf ; pop %0 \n\t" \
- : "=a" (__eax), "=c" (__ecx) \
- : /* no inputs */ \
- : "cc" \
- ); \
- bool __result = (__eax ^ __ecx) & 0x00200000; \
- __result; \
-})
-/* save EBX around CPUID, because gcc doesn't like it to be clobbered with -fPIC */
-# define x86_cpuid(input, eax, ebx, ecx, edx) \
- __asm__ __volatile__ ( \
- /* save ebx in esi */ \
- "mov %%ebx, %%esi \n\t" \
- /* get CPUID with eax=input */ \
- "cpuid \n\t" \
- /* swap ebx and esi */ \
- "xchg %%ebx, %%esi" \
- : "=a" (eax), "=S" (ebx), \
- "=c" (ecx), "=d" (edx) \
- : "0" (input) \
- : "cc")
-#elif defined __x86_64__ || defined __amd64__
-/* CPUID is always present on AMD64, see:
- * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24594.pdf
- * "AMD64 Architecture Programmer's Manual Volume 3",
- * "Appendix D: Instruction Subsets and CPUID Feature Sets"
- */
-# define x86_has_cpuid() (1)
-/* save EBX around CPUID, because gcc doesn't like it to be clobbered with -fPIC */
-# define x86_cpuid(input, eax, ebx, ecx, edx) \
- __asm__ __volatile__ ( \
- /* save ebx in esi */ \
- "mov %%rbx, %%rsi \n\t" \
- /* get CPUID with eax=input */ \
- "cpuid \n\t" \
- /* swap ebx and esi */ \
- "xchg %%rbx, %%rsi" \
- : "=a" (eax), "=S" (ebx), \
- "=c" (ecx), "=d" (edx) \
- : "0" (input) \
- : "cc")
-#else
-# define x86_has_cpuid() (false)
-# define x86_cpuid(input, eax, ebx, ecx, edx) do {} while (0)
-#endif
-
-
-static jmp_buf cpu_info_jmp_buf;
-
-static void BIRNET_NORETURN
-cpu_info_sigill_handler (int dummy)
-{
- longjmp (cpu_info_jmp_buf, 1);
-}
-
-static bool
-get_x86_cpu_features (BirnetCPUInfo *ci,
- char vendor[13])
-{
- memset (ci, 0, sizeof (*ci));
- /* check if the CPUID instruction is supported */
- if (!x86_has_cpuid ())
- return false;
-
- /* query intel CPUID range */
- unsigned int eax, ebx, ecx, edx;
- x86_cpuid (0, eax, ebx, ecx, edx);
- unsigned int v_ebx = ebx, v_ecx = ecx, v_edx = edx;
- *((unsigned int*) &vendor[0]) = ebx;
- *((unsigned int*) &vendor[4]) = edx;
- *((unsigned int*) &vendor[8]) = ecx;
- vendor[12] = 0;
- if (eax >= 1) /* may query version and feature information */
- {
- x86_cpuid (1, eax, ebx, ecx, edx);
- if (ecx & (1 << 0))
- ci->x86_sse3 = true;
- if (edx & (1 << 0))
- ci->x86_fpu = true;
- if (edx & (1 << 4))
- ci->x86_tsc = true;
- if (edx & (1 << 23))
- ci->x86_mmx = true;
- if (edx & (1 << 25))
- {
- ci->x86_sse = true;
- ci->x86_mmxext = true;
- }
- if (edx & (1 << 26))
- ci->x86_sse2 = true;
- if (edx & (1 << 28))
- ci->x86_htt = true;
- /* http://download.intel.com/design/Xeon/applnots/24161830.pdf
- * "Intel Processor Identificaiton and the CPUID Instruction"
- */
- }
-
- /* query extended CPUID range */
- x86_cpuid (0x80000000, eax, ebx, ecx, edx);
- if (eax >= 0x80000001 && /* may query extended feature information */
- v_ebx == 0x68747541 && /* AuthenticAMD */
- v_ecx == 0x444d4163 && v_edx == 0x69746e65)
- {
- x86_cpuid (0x80000001, eax, ebx, ecx, edx);
- if (edx & (1 << 31))
- ci->x86_3dnow = true;
- if (edx & (1 << 22))
- ci->x86_mmxext = true;
- if (edx & (1 << 30))
- ci->x86_3dnowext = true;
- /* www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf
- * "AMD CPUID Specification"
- */
- }
-
- /* check system support for SSE */
- if (ci->x86_sse)
- {
- struct sigaction action, old_action;
- action.sa_handler = cpu_info_sigill_handler;
- sigemptyset (&action.sa_mask);
- action.sa_flags = SA_NOMASK;
- sigaction (SIGILL, &action, &old_action);
- if (setjmp (cpu_info_jmp_buf) == 0)
- {
- unsigned int mxcsr;
- __asm__ __volatile__ ("stmxcsr %0 ; sfence ; emms" : "=m" (mxcsr));
- /* executed SIMD instructions without exception */
- ci->x86_ssesys = true;
- }
- else
- {
- /* signal handler jumped here */
- // g_printerr ("caught SIGILL\n");
- }
- sigaction (SIGILL, &old_action, NULL);
- }
-
- return true;
-}
-
-static BirnetCPUInfo global_cpu_info; /* = 0; */
-
-const BirnetCPUInfo*
-birnet_cpu_info (void)
-{
- return &global_cpu_info;
-}
-
-void
-_birnet_init_cpuinfo (void)
-{
- static char vendor_buffer[13];
- BirnetCPUInfo lci;
- memset (&lci, 0, sizeof (lci));
- if (get_x86_cpu_features (&lci, vendor_buffer))
- {
- lci.machine = get_arch_name();
- lci.cpu_vendor = vendor_buffer;
- }
- else
- {
- memset (&lci, 0, sizeof (lci));
- lci.machine = get_arch_name();
- lci.cpu_vendor = "unknown";
- }
- global_cpu_info = lci;
-}
-
-gchar*
-birnet_cpu_info_string (const BirnetCPUInfo *cpu_info)
-{
- GString *gstring = g_string_new ("");
- g_string_append_printf (gstring,
- "CPU Architecture: %s\n"
- "CPU Vendor: %s\n",
- cpu_info->machine, cpu_info->cpu_vendor);
- /* processor flags */
- GString *pflags = g_string_new ("");
- if (cpu_info->x86_fpu)
- g_string_append_printf (pflags, " FPU");
- if (cpu_info->x86_tsc)
- g_string_append_printf (pflags, " TSC");
- if (cpu_info->x86_htt)
- g_string_append_printf (pflags, " HTT");
- /* MMX flags */
- GString *mflags = g_string_new ("");
- if (cpu_info->x86_mmx)
- g_string_append_printf (mflags, " MMX");
- if (cpu_info->x86_mmxext)
- g_string_append_printf (mflags, " MMXEXT");
- /* SSE flags */
- GString *sflags = g_string_new ("");
- if (cpu_info->x86_sse)
- g_string_append_printf (sflags, " SSE");
- if (cpu_info->x86_sse2)
- g_string_append_printf (sflags, " SSE2");
- if (cpu_info->x86_sse3)
- g_string_append_printf (sflags, " SSE3");
- if (cpu_info->x86_ssesys)
- g_string_append_printf (sflags, " SSESYS");
- /* 3DNOW flags */
- GString *nflags = g_string_new ("");
- if (cpu_info->x86_3dnow)
- g_string_append_printf (nflags, " 3DNOW");
- if (cpu_info->x86_3dnowext)
- g_string_append_printf (nflags, " 3DNOWEXT");
- /* flag output */
- if (pflags->len)
- g_string_append_printf (gstring, "CPU Features: %s\n", pflags->str);
- if (mflags->len)
- g_string_append_printf (gstring, "CPU Integer SIMD:%s\n", mflags->str);
- if (sflags->len)
- g_string_append_printf (gstring, "CPU Float SIMD: %s\n", sflags->str);
- if (nflags->len)
- g_string_append_printf (gstring, "CPU Media SIMD: %s\n", nflags->str);
- g_string_free (nflags, TRUE);
- g_string_free (sflags, TRUE);
- g_string_free (mflags, TRUE);
- g_string_free (pflags, TRUE);
- /* done */
- return g_string_free (gstring, FALSE);
-}
Copied: trunk/birnet/birnetcpu.cc (from rev 3937, trunk/birnet/birnetcpu.c)
===================================================================
--- trunk/birnet/birnetcpu.c 2006-10-06 16:55:46 UTC (rev 3937)
+++ trunk/birnet/birnetcpu.cc 2006-10-06 21:53:52 UTC (rev 3939)
@@ -0,0 +1,305 @@
+/* BirnetCPU
+ * Copyright (C) 2006 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <glib.h>
+#include "birnetcpu.hh"
+#include <setjmp.h>
+#include <signal.h>
+#include <string.h>
+
+namespace Birnet {
+
+/* figure architecture name from compiler */
+static const char*
+get_arch_name (void)
+{
+#if defined __alpha__
+ return "Alpha";
+#elif defined __frv__
+ return "frv";
+#elif defined __s390__
+ return "s390";
+#elif defined __m32c__
+ return "m32c";
+#elif defined sparc
+ return "Sparc";
+#elif defined __m32r__
+ return "m32r";
+#elif defined __x86_64__ || defined __amd64__
+ return "AMD64";
+#elif defined __ia64__
+ return "Intel Itanium";
+#elif defined __m68k__
+ return "mc68000";
+#elif defined __powerpc__ || defined PPC || defined powerpc || defined __PPC__
+ return "PPC";
+#elif defined __arc__
+ return "arc";
+#elif defined __arm__
+ return "Arm";
+#elif defined __mips__ || defined mips
+ return "Mips";
+#elif defined __tune_i686__ || defined __i686__
+ return "i686";
+#elif defined __tune_i586__ || defined __i586__
+ return "i586";
+#elif defined __tune_i486__ || defined __i486__
+ return "i486";
+#elif defined i386 || defined __i386__
+ return "i386";
+#else
+ return "unknown-arch";
+#endif
+}
+
+/* --- X86 detection via CPUID --- */
+#if defined __i386__
+# define x86_has_cpuid() ({ \
+ unsigned int __eax, __ecx; \
+ __asm__ __volatile__ \
+ ( \
+ /* copy EFLAGS into eax and ecx */ \
+ "pushf ; pop %0 ; mov %0, %1 \n\t" \
+ /* toggle the ID bit and store back to EFLAGS */ \
+ "xor $0x200000, %0 ; push %0 ; popf \n\t" \
+ /* read back EFLAGS with possibly modified ID bit */ \
+ "pushf ; pop %0 \n\t" \
+ : "=a" (__eax), "=c" (__ecx) \
+ : /* no inputs */ \
+ : "cc" \
+ ); \
+ bool __result = (__eax ^ __ecx) & 0x00200000; \
+ __result; \
+})
+/* save EBX around CPUID, because gcc doesn't like it to be clobbered with -fPIC */
+# define x86_cpuid(input, eax, ebx, ecx, edx) \
+ __asm__ __volatile__ ( \
+ /* save ebx in esi */ \
+ "mov %%ebx, %%esi \n\t" \
+ /* get CPUID with eax=input */ \
+ "cpuid \n\t" \
+ /* swap ebx and esi */ \
+ "xchg %%ebx, %%esi" \
+ : "=a" (eax), "=S" (ebx), \
+ "=c" (ecx), "=d" (edx) \
+ : "0" (input) \
+ : "cc")
+#elif defined __x86_64__ || defined __amd64__
+/* CPUID is always present on AMD64, see:
+ * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/24594.pdf
+ * "AMD64 Architecture Programmer's Manual Volume 3",
+ * "Appendix D: Instruction Subsets and CPUID Feature Sets"
+ */
+# define x86_has_cpuid() (1)
+/* save EBX around CPUID, because gcc doesn't like it to be clobbered with -fPIC */
+# define x86_cpuid(input, eax, ebx, ecx, edx) \
+ __asm__ __volatile__ ( \
+ /* save ebx in esi */ \
+ "mov %%rbx, %%rsi \n\t" \
+ /* get CPUID with eax=input */ \
+ "cpuid \n\t" \
+ /* swap ebx and esi */ \
+ "xchg %%rbx, %%rsi" \
+ : "=a" (eax), "=S" (ebx), \
+ "=c" (ecx), "=d" (edx) \
+ : "0" (input) \
+ : "cc")
+#else
+# define x86_has_cpuid() (false)
+# define x86_cpuid(input, eax, ebx, ecx, edx) do {} while (0)
+#endif
+
+
+static jmp_buf cpu_info_jmp_buf;
+
+static void BIRNET_NORETURN
+cpu_info_sigill_handler (int dummy)
+{
+ longjmp (cpu_info_jmp_buf, 1);
+}
+
+static bool
+get_x86_cpu_features (CPUInfo *ci,
+ char vendor[13])
+{
+ memset (ci, 0, sizeof (*ci));
+ /* check if the CPUID instruction is supported */
+ if (!x86_has_cpuid ())
+ return false;
+
+ /* query intel CPUID range */
+ unsigned int eax, ebx, ecx, edx;
+ x86_cpuid (0, eax, ebx, ecx, edx);
+ unsigned int v_ebx = ebx, v_ecx = ecx, v_edx = edx;
+ *((unsigned int*) &vendor[0]) = ebx;
+ *((unsigned int*) &vendor[4]) = edx;
+ *((unsigned int*) &vendor[8]) = ecx;
+ vendor[12] = 0;
+ if (eax >= 1) /* may query version and feature information */
+ {
+ x86_cpuid (1, eax, ebx, ecx, edx);
+ if (ecx & (1 << 0))
+ ci->x86_sse3 = true;
+ if (edx & (1 << 0))
+ ci->x86_fpu = true;
+ if (edx & (1 << 4))
+ ci->x86_tsc = true;
+ if (edx & (1 << 23))
+ ci->x86_mmx = true;
+ if (edx & (1 << 25))
+ {
+ ci->x86_sse = true;
+ ci->x86_mmxext = true;
+ }
+ if (edx & (1 << 26))
+ ci->x86_sse2 = true;
+ if (edx & (1 << 28))
+ ci->x86_htt = true;
+ /* http://download.intel.com/design/Xeon/applnots/24161830.pdf
+ * "Intel Processor Identificaiton and the CPUID Instruction"
+ */
+ }
+
+ /* query extended CPUID range */
+ x86_cpuid (0x80000000, eax, ebx, ecx, edx);
+ if (eax >= 0x80000001 && /* may query extended feature information */
+ v_ebx == 0x68747541 && /* AuthenticAMD */
+ v_ecx == 0x444d4163 && v_edx == 0x69746e65)
+ {
+ x86_cpuid (0x80000001, eax, ebx, ecx, edx);
+ if (edx & (1 << 31))
+ ci->x86_3dnow = true;
+ if (edx & (1 << 22))
+ ci->x86_mmxext = true;
+ if (edx & (1 << 30))
+ ci->x86_3dnowext = true;
+ /* www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf
+ * "AMD CPUID Specification"
+ */
+ }
+
+ /* check system support for SSE */
+ if (ci->x86_sse)
+ {
+ struct sigaction action, old_action;
+ action.sa_handler = cpu_info_sigill_handler;
+ sigemptyset (&action.sa_mask);
+ action.sa_flags = SA_NOMASK;
+ sigaction (SIGILL, &action, &old_action);
+ if (setjmp (cpu_info_jmp_buf) == 0)
+ {
+ unsigned int mxcsr;
+ __asm__ __volatile__ ("stmxcsr %0 ; sfence ; emms" : "=m" (mxcsr));
+ /* executed SIMD instructions without exception */
+ ci->x86_ssesys = true;
+ }
+ else
+ {
+ /* signal handler jumped here */
+ // g_printerr ("caught SIGILL\n");
+ }
+ sigaction (SIGILL, &old_action, NULL);
+ }
+
+ return true;
+}
+
+static CPUInfo global_cpu_info; /* = 0; */
+
+const CPUInfo*
+cpu_info (void)
+{
+ return &global_cpu_info;
+}
+
+void
+_birnet_init_cpuinfo (void)
+{
+ static char vendor_buffer[13];
+ CPUInfo lci;
+ memset (&lci, 0, sizeof (lci));
+ if (get_x86_cpu_features (&lci, vendor_buffer))
+ {
+ lci.machine = get_arch_name();
+ lci.cpu_vendor = vendor_buffer;
+ }
+ else
+ {
+ memset (&lci, 0, sizeof (lci));
+ lci.machine = get_arch_name();
+ lci.cpu_vendor = "unknown";
+ }
+ global_cpu_info = lci;
+}
+
+char*
+cpu_info_string (const CPUInfo *cpu_info)
+{
+ GString *gstring = g_string_new ("");
+ g_string_append_printf (gstring,
+ "CPU Architecture: %s\n"
+ "CPU Vendor: %s\n",
+ cpu_info->machine, cpu_info->cpu_vendor);
+ /* processor flags */
+ GString *pflags = g_string_new ("");
+ if (cpu_info->x86_fpu)
+ g_string_append_printf (pflags, " FPU");
+ if (cpu_info->x86_tsc)
+ g_string_append_printf (pflags, " TSC");
+ if (cpu_info->x86_htt)
+ g_string_append_printf (pflags, " HTT");
+ /* MMX flags */
+ GString *mflags = g_string_new ("");
+ if (cpu_info->x86_mmx)
+ g_string_append_printf (mflags, " MMX");
+ if (cpu_info->x86_mmxext)
+ g_string_append_printf (mflags, " MMXEXT");
+ /* SSE flags */
+ GString *sflags = g_string_new ("");
+ if (cpu_info->x86_sse)
+ g_string_append_printf (sflags, " SSE");
+ if (cpu_info->x86_sse2)
+ g_string_append_printf (sflags, " SSE2");
+ if (cpu_info->x86_sse3)
+ g_string_append_printf (sflags, " SSE3");
+ if (cpu_info->x86_ssesys)
+ g_string_append_printf (sflags, " SSESYS");
+ /* 3DNOW flags */
+ GString *nflags = g_string_new ("");
+ if (cpu_info->x86_3dnow)
+ g_string_append_printf (nflags, " 3DNOW");
+ if (cpu_info->x86_3dnowext)
+ g_string_append_printf (nflags, " 3DNOWEXT");
+ /* flag output */
+ if (pflags->len)
+ g_string_append_printf (gstring, "CPU Features: %s\n", pflags->str);
+ if (mflags->len)
+ g_string_append_printf (gstring, "CPU Integer SIMD:%s\n", mflags->str);
+ if (sflags->len)
+ g_string_append_printf (gstring, "CPU Float SIMD: %s\n", sflags->str);
+ if (nflags->len)
+ g_string_append_printf (gstring, "CPU Media SIMD: %s\n", nflags->str);
+ g_string_free (nflags, TRUE);
+ g_string_free (sflags, TRUE);
+ g_string_free (mflags, TRUE);
+ g_string_free (pflags, TRUE);
+ /* done */
+ return g_string_free (gstring, FALSE);
+}
+
+} // Birnet
Deleted: trunk/birnet/birnetcpu.h
===================================================================
--- trunk/birnet/birnetcpu.h 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetcpu.h 2006-10-06 21:53:52 UTC (rev 3939)
@@ -1,48 +0,0 @@
-/* BirnetCPU
- * Copyright (C) 2006 Tim Janik
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#ifndef __BIRNET_CPU_H__
-#define __BIRNET_CPU_H__
-
-#include <birnet/birnetcore.h>
-
-G_BEGIN_DECLS
-
-typedef struct {
- /* architecture name */
- const char *machine;
- /* CPU Vendor ID */
- const char *cpu_vendor;
- /* CPU features on X86 */
- BirnetUInt x86_fpu : 1, x86_tsc : 1, x86_htt : 1;
- BirnetUInt x86_mmx : 1, x86_mmxext : 1, x86_3dnow : 1, x86_3dnowext : 1;
- BirnetUInt x86_sse : 1, x86_sse2 : 1, x86_sse3 : 1, x86_ssesys : 1;
-} BirnetCPUInfo;
-
-/* --- functions --- */
-const BirnetCPUInfo* birnet_cpu_info (void);
-gchar* birnet_cpu_info_string (const BirnetCPUInfo *cpu_info);
-
-/* --- implementation --- */
-void _birnet_init_cpuinfo (void);
-
-G_END_DECLS
-
-#endif /* __BIRNET_CPU_H__ */
-
-/* vim:set ts=8 sts=2 sw=2: */
Copied: trunk/birnet/birnetcpu.hh (from rev 3937, trunk/birnet/birnetcpu.h)
===================================================================
--- trunk/birnet/birnetcpu.h 2006-10-06 16:55:46 UTC (rev 3937)
+++ trunk/birnet/birnetcpu.hh 2006-10-06 21:53:52 UTC (rev 3939)
@@ -0,0 +1,38 @@
+/* BirnetCPU
+ * Copyright (C) 2006 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __BIRNET_CPU_HH__
+#define __BIRNET_CPU_HH__
+
+#include <birnet/birnetutilsxx.hh>
+
+namespace Birnet {
+
+typedef BirnetCPUInfo CPUInfo;
+
+/* --- functions --- */
+const CPUInfo* cpu_info (void);
+char* cpu_info_string (const CPUInfo *cpu_info);
+
+/* --- implementation --- */
+void _birnet_init_cpuinfo (void);
+
+} // Birnet
+
+#endif /* __BIRNET_CPU_HH__ */
+/* vim:set ts=8 sts=2 sw=2: */
Modified: trunk/birnet/birnetmsg.cc
===================================================================
--- trunk/birnet/birnetmsg.cc 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetmsg.cc 2006-10-06 21:53:52 UTC (rev 3939)
@@ -16,6 +16,7 @@
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
+#include <glib.h>
#include "birnetmsg.hh"
namespace Birnet {
Modified: trunk/birnet/birnetmsg.hh
===================================================================
--- trunk/birnet/birnetmsg.hh 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetmsg.hh 2006-10-06 21:53:52 UTC (rev 3939)
@@ -19,8 +19,8 @@
#ifndef __BIRNET_MSG_HH__
#define __BIRNET_MSG_HH__
-#include <birnet/birnetcore.h>
-#include <birnet/birnetutilsxx.hh> // FIXME: need String in core.hh
+#include <birnet/birnetutilsxx.hh>
+#include <stdarg.h>
namespace Birnet {
@@ -45,23 +45,23 @@
va_list varargs);
};
struct Text0 : public Part { /* message title */
- Text0 (const char *format, ...) G_GNUC_PRINTF (2, 3) { va_list a; va_start (a, format); setup ('0', format, a); va_end (a); }
+ Text0 (const char *format, ...) BIRNET_PRINTF (2, 3) { va_list a; va_start (a, format); setup ('0', format, a); va_end (a); }
Text0 (const String &s) { setup ('0', s); }
};
struct Text1 : public Part { /* primary message */
- Text1 (const char *format, ...) G_GNUC_PRINTF (2, 3) { va_list a; va_start (a, format); setup ('1', format, a); va_end (a); }
+ Text1 (const char *format, ...) BIRNET_PRINTF (2, 3) { va_list a; va_start (a, format); setup ('1', format, a); va_end (a); }
Text1 (const String &s) { setup ('1', s); }
};
struct Text2 : public Part { /* secondary message (lengthy) */
- Text2 (const char *format, ...) G_GNUC_PRINTF (2, 3) { va_list a; va_start (a, format); setup ('2', format, a); va_end (a); }
+ Text2 (const char *format, ...) BIRNET_PRINTF (2, 3) { va_list a; va_start (a, format); setup ('2', format, a); va_end (a); }
Text2 (const String &s) { setup ('2', s); }
};
struct Text3 : public Part { /* message details */
- Text3 (const char *format, ...) G_GNUC_PRINTF (2, 3) { va_list a; va_start (a, format); setup ('3', format, a); va_end (a); }
+ Text3 (const char *format, ...) BIRNET_PRINTF (2, 3) { va_list a; va_start (a, format); setup ('3', format, a); va_end (a); }
Text3 (const String &s) { setup ('3', s); }
};
struct Check : public Part { /* user switch */
- Check (const char *format, ...) G_GNUC_PRINTF (2, 3) { va_list a; va_start (a, format); setup ('c', format, a); va_end (a); }
+ Check (const char *format, ...) BIRNET_PRINTF (2, 3) { va_list a; va_start (a, format); setup ('c', format, a); va_end (a); }
Check (const String &s) { setup ('c', s); }
};
typedef Text0 Title; /* message title */
Modified: trunk/birnet/birnettests.h
===================================================================
--- trunk/birnet/birnettests.h 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnettests.h 2006-10-06 21:53:52 UTC (rev 3939)
@@ -148,6 +148,7 @@
/* --- C++ test initialization --- */
#ifdef __cplusplus
+namespace Birnet {
static inline void
birnet_init_test (int *argc,
char ***argv)
@@ -159,11 +160,12 @@
{ "stand-alone", "true" },
{ NULL }
};
- birnet_init_extended (argc, argv, NULL, ivalues);
+ birnet_init (argc, argv, NULL, ivalues);
unsigned int flags = g_log_set_always_fatal ((GLogLevelFlags) G_LOG_FATAL_MASK);
g_log_set_always_fatal ((GLogLevelFlags) (flags | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL));
g_printerr ("TEST: %s\n", g_get_prgname());
}
+} // Birnet
#endif
BIRNET_EXTERN_C_END();
Modified: trunk/birnet/birnetthread.c
===================================================================
--- trunk/birnet/birnetthread.c 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetthread.c 2006-10-06 21:53:52 UTC (rev 3939)
@@ -41,6 +41,19 @@
#define THREAD_REF_COUNT(thread) (thread->ref_field & ~FLOATING_FLAG)
#define THREAD_CAS(thread, oldval, newval) g_atomic_int_compare_and_exchange ((int*) &thread->ref_field, oldval, newval)
+/* --- short integer types --- */ // FIXME: those shouldn't be defined here
+typedef BirnetUInt8 uint8;
+typedef BirnetUInt16 uint16;
+typedef BirnetUInt32 uint32;
+typedef BirnetUInt64 uint64;
+typedef BirnetInt8 int8;
+typedef BirnetInt16 int16;
+typedef BirnetInt32 int32;
+typedef BirnetInt64 int64;
+typedef BirnetUnichar unichar;
+#define BIRNET__RUNTIME_PROBLEM(ErrorWarningReturnAssertNotreach,domain,file,line,funcname,...) \
+ g_error (__VA_ARGS__) // FIXME
+
/* --- structures --- */
struct _BirnetThread
{
Modified: trunk/birnet/birnetthread.h
===================================================================
--- trunk/birnet/birnetthread.h 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetthread.h 2006-10-06 21:53:52 UTC (rev 3939)
@@ -22,7 +22,7 @@
#include <stdbool.h>
#include <glib.h>
-#include <birnet/birnetcore.h>
+#include <birnet/birnetcdefs.h>
G_BEGIN_DECLS
Deleted: trunk/birnet/birnetutils.cc
===================================================================
--- trunk/birnet/birnetutils.cc 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetutils.cc 2006-10-06 21:53:52 UTC (rev 3939)
@@ -1,507 +0,0 @@
-/* Birnet
- * Copyright (C) 2006 Tim Janik
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#include "birnetutils.hh"
-#include "birnetmsg.hh"
-#include "birnetthreadxx.hh"
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <wchar.h>
-
-#ifndef _
-#define _(string) (string) // FIXME
-#endif
-
-namespace Birnet {
-
-/* --- url handling --- */
-bool
-url_test_show (const char *url)
-{
- static struct {
- const char *prg, *arg1, *prefix, *postfix;
- volatile bool disabled;
- } www_browsers[] = {
- /* program */ /* arg1 */ /* prefix+URL+postfix */
- /* system browser launchers */
- { "sensible-browser", NULL, "", "" },
- { "x-www-browser", NULL, "", "" },
- { "htmlview", NULL, "", "" },
- /* portable browser launchers */
- { "xdg-open", NULL, "", "" },
-#if 1
- /* desktop browser launchers */
- { "gnome-open", NULL, "", "" },
- { "kfmclient", "openURL", "", "" },
- { "gnome-moz-remote", "--newwin" "", "" },
- /* specific browser programs */
- { "firefox", NULL, "", "" },
- { "mozilla-firefox", NULL, "", "" },
- { "mozilla", NULL, "", "" },
- { "opera", "-newwindow", "", "" },
- { "konqueror", NULL, "", "" },
-#endif
- /* above, we give system browser launchers precedence over xdg-open
- * (especially the debian sensible-browser script), because xdg-open
- * tends to exhibit bugs in desktop browser launchers still (e.g.
- * gnome-open not honouring the users browser setting for file:///
- * urls).
- */
- };
- uint i;
- for (i = 0; i < G_N_ELEMENTS (www_browsers); i++)
- if (!www_browsers[i].disabled)
- {
- char *args[128] = { 0, };
- uint n = 0;
- args[n++] = (char*) www_browsers[i].prg;
- if (www_browsers[i].arg1)
- args[n++] = (char*) www_browsers[i].arg1;
- char *string = g_strconcat (www_browsers[i].prefix, url, www_browsers[i].postfix, NULL);
- args[n] = string;
- GError *error = NULL;
- bool success = g_spawn_async (NULL, /* cwd */
- args,
- NULL, /* envp */
- G_SPAWN_SEARCH_PATH,
- NULL, /* child_setup() */
- NULL, /* user_data */
- NULL, /* child_pid */
- &error);
- g_free (string);
- // g_printerr ("show \"%s\": %s: %s\n", url, args[0], error ? error->message : "Ok");
- g_clear_error (&error);
- if (success)
- return TRUE;
- www_browsers[i].disabled = true;
- }
- /* reset disabled states if no browser could be found */
- for (i = 0; i < G_N_ELEMENTS (www_browsers); i++)
- www_browsers[i].disabled = false;
- return false;
-}
-
-static void
-browser_launch_warning (const char *url)
-{
- Msg::display (Msg::WARNING,
- Msg::Title (_("Launch Web Browser")),
- Msg::Text1 (_("Failed to launch a web browser executable")),
- Msg::Text2 (_("No suitable web browser executable could be found to be executed and to display the URL: %s"), url),
- Msg::Check (_("Show messages about web browser launch problems")));
-}
-
-void
-url_show (const char *url)
-{
- bool success = url_test_show (url);
- if (!success)
- browser_launch_warning (url);
-}
-
-static void
-unlink_file_name (gpointer data)
-{
- char *file_name = (char*) data;
- while (unlink (file_name) < 0 && errno == EINTR);
- g_free (file_name);
-}
-
-static const gchar*
-url_create_redirect (const char *url,
- const char *url_title,
- const char *cookie)
-{
- const char *ver = "0.5";
- gchar *tname = NULL;
- gint fd = -1;
- while (fd < 0)
- {
- g_free (tname);
- tname = g_strdup_printf ("/tmp/Url%08X%04X.html", (int) lrand48(), getpid());
- fd = open (tname, O_WRONLY | O_CREAT | O_EXCL, 00600);
- if (fd < 0 && errno != EEXIST)
- {
- g_free (tname);
- return NULL;
- }
- }
- char *text = g_strdup_printf ("<!DOCTYPE HTML SYSTEM>\n"
- "<html><head>\n"
- "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"
- "<meta http-equiv=\"refresh\" content=\"0; URL=%s\">\n"
- "<meta http-equiv=\"set-cookie\" content=\"%s\">\n"
- "<title>%s</title>\n"
- "</head><body>\n"
- "<h1>%s</h1>\n"
- "<b>Document Redirection</b><br>\n"
- "Your browser is being redirected.\n"
- "If it does not support automatic redirections, try <a href=\"%s\">%s</a>.\n"
- "<hr>\n"
- "<address>BirnetUrl/%s file redirect</address>\n"
- "</body></html>\n",
- url, cookie, url_title, url_title, url, url, ver);
- int w, c, l = strlen (text);
- do
- w = write (fd, text, l);
- while (w < 0 && errno == EINTR);
- g_free (text);
- do
- c = close (fd);
- while (c < 0 && errno == EINTR);
- if (w != l || c < 0)
- {
- while (unlink (tname) < 0 && errno == EINTR)
- {}
- g_free (tname);
- return NULL;
- }
- cleanup_add (60 * 1000, unlink_file_name, tname); /* free tname */
- return tname;
-}
-
-bool
-url_test_show_with_cookie (const char *url,
- const char *url_title,
- const char *cookie)
-{
- const char *redirect = url_create_redirect (url, url_title, cookie);
- if (redirect)
- return url_test_show (redirect);
- else
- return url_test_show (url);
-}
-
-void
-url_show_with_cookie (const char *url,
- const char *url_title,
- const char *cookie)
-{
- bool success = url_test_show_with_cookie (url, url_title, cookie);
- if (!success)
- browser_launch_warning (url);
-}
-
-/* --- cleanups --- */
-typedef struct {
- uint id;
- GDestroyNotify handler;
- void *data;
-} Cleanup;
-
-static Mutex cleanup_mutex;
-static GSList *cleanup_list = NULL;
-
-static void
-cleanup_exec_Lm (Cleanup *cleanup)
-{
- cleanup_list = g_slist_remove (cleanup_list, cleanup);
- g_source_remove (cleanup->id);
- GDestroyNotify handler = cleanup->handler;
- void *data = cleanup->data;
- g_free (cleanup);
- cleanup_mutex.unlock();
- handler (data);
- cleanup_mutex.lock();
-}
-
-/**
- * Force all cleanup handlers (see birnet_cleanup_add()) to be immediately
- * executed. This function should be called at program exit to execute
- * cleanup handlers which have timeouts that have not yet expired.
- */
-void
-cleanup_force_handlers (void)
-{
- cleanup_mutex.lock();
- while (cleanup_list)
- cleanup_exec_Lm ((Cleanup*) cleanup_list->data);
- cleanup_mutex.unlock();
-}
-
-static gboolean
-cleanup_exec (gpointer data)
-{
- cleanup_mutex.lock();
- cleanup_exec_Lm ((Cleanup*) data);
- cleanup_mutex.unlock();
- return FALSE;
-}
-
-/**
- * @param timeout_ms timeout in milliseconds
- * @param handler cleanup handler to run
- * @param data cleanup handler data
- *
- * Register a cleanup handler, the @a handler is guaranteed to be run
- * asyncronously (i.e. not from within cleanup_add()). The cleanup
- * handler will be called as soon as @a timeout_ms has elapsed or
- * cleanup_force_handlers() is called.
- */
-uint
-cleanup_add (guint timeout_ms,
- GDestroyNotify handler,
- void *data)
-{
- Cleanup *cleanup = g_new0 (Cleanup, 1);
- cleanup->handler = handler;
- cleanup->data = data;
- cleanup->id = g_timeout_add (timeout_ms, cleanup_exec, cleanup);
- cleanup_mutex.lock();
- cleanup_list = g_slist_prepend (cleanup_list, cleanup);
- cleanup_mutex.unlock();
- return cleanup->id;
-}
-
-/* --- string utils --- */
-void
-memset4 (guint32 *mem,
- guint32 filler,
- guint length)
-{
- BIRNET_STATIC_ASSERT (sizeof (*mem) == 4);
- BIRNET_STATIC_ASSERT (sizeof (filler) == 4);
- BIRNET_STATIC_ASSERT (sizeof (wchar_t) == 4);
- wmemset ((wchar_t*) mem, filler, length);
-}
-
-/* --- memory utils --- */
-void*
-malloc_aligned (gsize total_size,
- gsize alignment,
- guint8 **free_pointer)
-{
- uint8 *aligned_mem = (uint8*) g_malloc (total_size);
- *free_pointer = aligned_mem;
- if (!alignment || !(ptrdiff_t) aligned_mem % alignment)
- return aligned_mem;
- g_free (aligned_mem);
- aligned_mem = (uint8*) g_malloc (total_size + alignment - 1);
- *free_pointer = aligned_mem;
- if ((ptrdiff_t) aligned_mem % alignment)
- aligned_mem += alignment - (ptrdiff_t) aligned_mem % alignment;
- return aligned_mem;
-}
-
-/* --- file testing --- */
-static int
-errno_check_file (const char *file_name,
- const char *mode)
-{
- uint access_mask = 0, nac = 0;
-
- if (strchr (mode, 'e')) /* exists */
- nac++, access_mask |= F_OK;
- if (strchr (mode, 'r')) /* readable */
- nac++, access_mask |= R_OK;
- if (strchr (mode, 'w')) /* writable */
- nac++, access_mask |= W_OK;
- bool check_exec = strchr (mode, 'x') != NULL;
- if (check_exec) /* executable */
- nac++, access_mask |= X_OK;
-
- /* on some POSIX systems, X_OK may succeed for root without any
- * executable bits set, so we also check via stat() below.
- */
- if (nac && access (file_name, access_mask) < 0)
- return -errno;
-
- bool check_file = strchr (mode, 'f') != NULL; /* open as file */
- bool check_dir = strchr (mode, 'd') != NULL; /* open as directory */
- bool check_link = strchr (mode, 'l') != NULL; /* open as link */
- bool check_char = strchr (mode, 'c') != NULL; /* open as character device */
- bool check_block = strchr (mode, 'b') != NULL; /* open as block device */
- bool check_pipe = strchr (mode, 'p') != NULL; /* open as pipe */
- bool check_socket = strchr (mode, 's') != NULL; /* open as socket */
-
- if (check_exec || check_file || check_dir || check_link || check_char || check_block || check_pipe || check_socket)
- {
- struct stat st;
-
- if (check_link)
- {
- if (lstat (file_name, &st) < 0)
- return -errno;
- }
- else if (stat (file_name, &st) < 0)
- return -errno;
-
- if (0)
- g_printerr ("file-check(\"%s\",\"%s\"): %s%s%s%s%s%s%s\n",
- file_name, mode,
- S_ISREG (st.st_mode) ? "f" : "",
- S_ISDIR (st.st_mode) ? "d" : "",
- S_ISLNK (st.st_mode) ? "l" : "",
- S_ISCHR (st.st_mode) ? "c" : "",
- S_ISBLK (st.st_mode) ? "b" : "",
- S_ISFIFO (st.st_mode) ? "p" : "",
- S_ISSOCK (st.st_mode) ? "s" : "");
-
- if (S_ISDIR (st.st_mode) && (check_file || check_link || check_char || check_block || check_pipe))
- return -EISDIR;
- if (check_file && !S_ISREG (st.st_mode))
- return -EINVAL;
- if (check_dir && !S_ISDIR (st.st_mode))
- return -ENOTDIR;
- if (check_link && !S_ISLNK (st.st_mode))
- return -EINVAL;
- if (check_char && !S_ISCHR (st.st_mode))
- return -ENODEV;
- if (check_block && !S_ISBLK (st.st_mode))
- return -ENOTBLK;
- if (check_pipe && !S_ISFIFO (st.st_mode))
- return -ENXIO;
- if (check_socket && !S_ISSOCK (st.st_mode))
- return -ENOTSOCK;
- if (check_exec && !(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
- return -EACCES; /* for root executable, any +x bit is good enough */
- }
-
- return 0;
-}
-
-/**
- * @param file possibly relative filename
- * @param mode feature string
- * @return TRUE if @a file adhears to @a mode
- *
- * Perform various checks on @a file and return whether all
- * checks passed. On failure, errno is set appropriately, and
- * FALSE is returned. Available features to be checked for are:
- * @itemize
- * @item e - @a file must exist
- * @item r - @a file must be readable
- * @item w - @a file must be writable
- * @item x - @a file must be executable
- * @item f - @a file must be a regular file
- * @item d - @a file must be a directory
- * @item l - @a file must be a symbolic link
- * @item c - @a file must be a character device
- * @item b - @a file must be a block device
- * @item p - @a file must be a named pipe
- * @item s - @a file must be a socket.
- * @done
- */
-bool
-file_check (const gchar *file,
- const gchar *mode)
-{
- int err = file && mode ? errno_check_file (file, mode) : -EFAULT;
- errno = err < 0 ? -err : 0;
- return errno == 0;
-}
-
-/**
- * @param file1 possibly relative filename
- * @param file2 possibly relative filename
- * @return TRUE if @a file1 and @a file2 are equal
- *
- * Check whether @a file1 and @a file2 are pointing to the same inode
- * in the same file system on the same device.
- */
-bool
-file_equals (const gchar *file1,
- const gchar *file2)
-{
- if (!file1 || !file2)
- return file1 == file2;
- struct stat st1 = { 0, }, st2 = { 0, };
- int err1 = 0, err2 = 0;
- errno = 0;
- if (stat (file1, &st1) < 0 && stat (file1, &st1) < 0)
- err1 = errno;
- errno = 0;
- if (stat (file2, &st2) < 0 && stat (file2, &st2) < 0)
- err2 = errno;
- if (err1 || err2)
- return err1 == err2;
- return (st1.st_dev == st2.st_dev &&
- st1.st_ino == st2.st_ino &&
- st1.st_rdev == st2.st_rdev);
-}
-
-/* --- zintern support --- */
-#include <zlib.h>
-
-/**
- * @param decompressed_size exact size of the decompressed data to be returned
- * @param cdata compressed data block
- * @param cdata_size exact size of the compressed data block
- * @returns decompressed data block or NULL in low memory situations
- *
- * Decompress the data from @a cdata of length @a cdata_size into a newly
- * allocated block of size @a decompressed_size which is returned.
- * The returned block needs to be freed with g_free().
- * This function is intended to decompress data which has been compressed
- * with the birnet-zintern utility, so no errors should occour during
- * decompression.
- * Consequently, if any error occours during decompression or if the resulting
- * data block is of a size other than @a decompressed_size, the program will
- * abort with an appropriate error message.
- * If not enough memory could be allocated for decompression, NULL is returned.
- */
-uint8*
-zintern_decompress (unsigned int decompressed_size,
- const unsigned char *cdata,
- unsigned int cdata_size)
-{
- uLongf dlen = decompressed_size;
- uint64 len = dlen + 1;
- uint8 *text = (uint8*) g_try_malloc (len);
- if (!text)
- return NULL; /* handle ENOMEM gracefully */
-
- int64 result = uncompress (text, &dlen, cdata, cdata_size);
- const char *err;
- switch (result)
- {
- case Z_OK:
- if (dlen == decompressed_size)
- {
- err = NULL;
- break;
- }
- /* fall through */
- case Z_DATA_ERROR:
- err = "internal data corruption";
- break;
- case Z_MEM_ERROR:
- err = "out of memory";
- g_free (text);
- return NULL; /* handle ENOMEM gracefully */
- break;
- case Z_BUF_ERROR:
- err = "insufficient buffer size";
- break;
- default:
- err = "unknown error";
- break;
- }
- if (err)
- g_error ("failed to decompress (%p, %u): %s", cdata, cdata_size, err);
-
- text[dlen] = 0;
- return text; /* success */
-}
-
-} // Birnet
Deleted: trunk/birnet/birnetutils.hh
===================================================================
--- trunk/birnet/birnetutils.hh 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetutils.hh 2006-10-06 21:53:52 UTC (rev 3939)
@@ -1,67 +0,0 @@
-/* Birnet
- * Copyright (C) 2006 Tim Janik
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#ifndef __BIRNET_UTILS_HH__
-#define __BIRNET_UTILS_HH__
-
-#include <birnet/birnetcore.h>
-
-namespace Birnet {
-
-/* --- url handling --- */
-void url_show (const char *url);
-void url_show_with_cookie (const char *url,
- const char *url_title,
- const char *cookie);
-bool url_test_show (const char *url);
-bool url_test_show_with_cookie (const char *url,
- const char *url_title,
- const char *cookie);
-
-/* --- cleanup registration --- */
-uint cleanup_add (uint timeout_ms,
- GDestroyNotify handler,
- void *data);
-void cleanup_force_handlers (void);
-
-/* --- string utils --- */
-void memset4 (uint32 *mem,
- uint32 filler,
- uint length);
-/* --- memory utils --- */
-void* malloc_aligned (gsize total_size,
- gsize alignment,
- uint8 **free_pointer);
-/* --- file testing --- */
-bool file_check (const char *file,
- const char *mode);
-bool file_equals (const char *file1,
- const char *file2);
-
-/* --- C++ demangling --- */
-char* cxx_demangle (const char *mangled_identifier); /* in birnetutilsxx.cc */
-
-/* --- zintern support --- */
-uint8* zintern_decompress (unsigned int decompressed_size,
- const unsigned char *cdata,
- unsigned int cdata_size);
-
-} // Birnet
-
-#endif /* __BIRNET_UTILS_HH__ */
-/* vim:set ts=8 sts=2 sw=2: */
Modified: trunk/birnet/birnetutilsxx.cc
===================================================================
--- trunk/birnet/birnetutilsxx.cc 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetutilsxx.cc 2006-10-06 21:53:52 UTC (rev 3939)
@@ -16,53 +16,85 @@
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
+#include <glib.h>
#include "birnetutilsxx.hh"
-#include "birnetutils.hh"
#include "birnetthreadxx.hh"
-#include "birnetcpu.h"
+#include "birnetmsg.hh"
+#include "birnetcpu.hh"
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <sys/time.h>
#include <vector>
#include <algorithm>
#include <cxxabi.h>
+#include <signal.h>
-extern "C" {
+#ifndef _
+#define _(s) s
+#endif
-/* --- demangling --- */
-gchar*
-birnet_cxx_demangle (const char *mangled_identifier) /* from birnetutils.h */
+extern "C" void _birnet_init_threads (void); // FIXME
+
+namespace Birnet {
+
+/* --- InitHooks --- */
+static void (*run_init_hooks) () = NULL;
+static InitHook *init_hooks = NULL;
+
+InitHook::InitHook (InitHookFunc _func,
+ int _priority) :
+ next (NULL), priority (_priority), hook (_func)
{
- int status = 0;
- char *malloced_result = abi::__cxa_demangle (mangled_identifier, NULL, NULL, &status);
- gchar *result = g_strdup (malloced_result && !status ? malloced_result : mangled_identifier);
- if (malloced_result)
- free (malloced_result);
- return result;
+ BIRNET_ASSERT (birnet_init_settings == NULL);
+ /* the above assertion guarantees single-threadedness */
+ next = init_hooks;
+ init_hooks = this;
+ run_init_hooks = invoke_hooks;
}
-/* --- initialization for C --- */
-static void (*birnet_init_cplusplus_func) (void) = NULL;
-static BirnetInitSettings default_init_settings = {
+void
+InitHook::invoke_hooks (void)
+{
+ std::vector<InitHook*> hv;
+ struct Sub {
+ static int
+ init_hook_cmp (const InitHook *const &v1,
+ const InitHook *const &v2)
+ {
+ return v1->priority < v2->priority ? -1 : v1->priority > v2->priority;
+ }
+ };
+ for (InitHook *ihook = init_hooks; ihook; ihook = ihook->next)
+ hv.push_back (ihook);
+ stable_sort (hv.begin(), hv.end(), Sub::init_hook_cmp);
+ for (std::vector<InitHook*>::iterator it = hv.begin(); it != hv.end(); it++)
+ (*it)->hook();
+}
+
+/* --- initialization --- */
+const InitSettings *birnet_init_settings = NULL;
+static InitSettings global_init_settings = {
false, /* stand_alone */
};
-BirnetInitSettings *birnet_init_settings = NULL;
static void
-birnet_init_settings_values (BirnetInitValue bivalues[])
+apply_settings_values (InitValue *value)
{
- BirnetInitValue *value = bivalues;
while (value->value_name)
{
if (strcmp (value->value_name, "stand-alone") == 0)
- birnet_init_settings->stand_alone = birnet_init_value_bool (value);
+ global_init_settings.stand_alone = init_value_bool (value);
value++;
}
}
void
-birnet_init_extended (int *argcp, /* declared in birnetcore.h */
- char ***argvp,
- const char *app_name,
- BirnetInitValue bivalues[])
+birnet_init (int *argcp,
+ char ***argvp,
+ const char *app_name,
+ InitValue ivalues[])
{
/* mandatory initial initialization */
if (!g_threads_got_initialized)
@@ -77,13 +109,13 @@
g_free (prg_name);
if (app_name && !g_get_application_name())
g_set_application_name (app_name);
- return; /* ignore repeated initializations */
+ return; /* simply ignore repeated initializations */
}
/* normal initialization */
- birnet_init_settings = &default_init_settings;
- if (bivalues)
- birnet_init_settings_values (bivalues);
+ birnet_init_settings = &global_init_settings;
+ if (ivalues)
+ apply_settings_values (ivalues);
if (prg_name)
g_set_prgname (prg_name);
g_free (prg_name);
@@ -101,14 +133,135 @@
/* initialize sub systems */
_birnet_init_cpuinfo();
_birnet_init_threads();
- if (birnet_init_cplusplus_func)
- birnet_init_cplusplus_func();
+ if (run_init_hooks)
+ run_init_hooks();
}
-} // "C"
+bool
+init_value_bool (InitValue *value)
+{
+ if (value->value_string)
+ switch (value->value_string[0])
+ {
+ case 0: // FIXME: use string_to_bool()
+ case '0': case 'f': case 'F':
+ case 'n': case 'N': /* false assigments */
+ return FALSE;
+ default:
+ return TRUE;
+ }
+ else
+ return ABS (value->value_num) >= 0.5;
+}
-namespace Birnet {
+double
+init_value_double (InitValue *value)
+{
+ if (value->value_string && value->value_string[0])
+ return g_strtod (value->value_string, NULL);
+ return value->value_num;
+}
+int64
+init_value_int (InitValue *value)
+{
+ if (value->value_string && value->value_string[0])
+ return strtoll (value->value_string, NULL, 0);
+ return value->value_num + 0.5;
+}
+
+/* --- assertions/warnings/errors --- */
+void
+raise_sigtrap ()
+{
+ raise (SIGTRAP);
+}
+
+static void
+stderr_print (bool bail_out,
+ const char *prefix,
+ const char *domain,
+ const char *file,
+ int line,
+ const char *funcname,
+ const char *pmsg,
+ const char *str)
+{
+ fflush (stdout);
+ String msg (bail_out ? "\n" : "");
+ if (domain)
+ msg += domain + String ("-") + prefix;
+ else
+ msg += prefix;
+ if (file)
+ {
+ char buffer[64];
+ sprintf (buffer, "%d", line);
+ msg += String (":") + file + String (":") + String (buffer);
+ }
+ if (funcname)
+ msg += String (":") + funcname + "()";
+ if (pmsg)
+ msg += String (": ") + pmsg;
+ if (str)
+ msg += String (": ") + str;
+ msg += "\n";
+ if (bail_out)
+ msg += "aborting...\n";
+ fputs (msg.c_str(), stderr);
+ fflush (stderr);
+}
+
+void
+birnet_runtime_problem (char ewran_tag,
+ const char *domain,
+ const char *file,
+ int line,
+ const char *funcname,
+ const char *msgformat,
+ ...)
+{
+ const bool noreturn_case = ewran_tag == 'E' || ewran_tag == 'A' || ewran_tag == 'N';
+ char *msg = NULL;
+ if (msgformat && msgformat[0])
+ {
+ va_list args;
+ va_start (args, msgformat);
+ msg = g_strdup_vprintf (msgformat, args);
+ va_end (args);
+ }
+ const char *prefix, *pmsg = NULL;
+ switch (ewran_tag)
+ {
+ case 'E':
+ prefix = "ERROR";
+ break;
+ case 'W':
+ prefix = "WARNING";
+ break;
+ case 'R':
+ prefix = "WARNING:";
+ pmsg = "Check failed";
+ break;
+ case 'A':
+ prefix = "ERROR";
+ pmsg = "Assertion failed";
+ break;
+ default:
+ case 'N':
+ prefix = "ERROR";
+ pmsg = "Assertion should not be reached";
+ break;
+ }
+ stderr_print (noreturn_case, prefix, domain, file, line, funcname, pmsg, msg);
+ g_free (msg);
+ if (noreturn_case)
+ {
+ BREAKPOINT();
+ abort();
+ }
+}
+
/* --- VirtualTypeid --- */
VirtualTypeid::~VirtualTypeid ()
{ /* virtual destructor ensures vtable */ }
@@ -136,39 +289,6 @@
return result;
}
-/* --- InitHooks --- */
-static InitHook *init_hooks = NULL;
-
-InitHook::InitHook (InitHookFunc _func,
- int _priority) :
- next (NULL), priority (_priority), hook (_func)
-{
- BIRNET_ASSERT (birnet_init_settings == NULL);
- /* the above assertion guarantees single-threadedness */
- next = init_hooks;
- init_hooks = this;
- birnet_init_cplusplus_func = invoke_hooks;
-}
-
-void
-InitHook::invoke_hooks (void)
-{
- std::vector<InitHook*> hv;
- struct Sub {
- static int
- init_hook_cmp (const InitHook *const &v1,
- const InitHook *const &v2)
- {
- return v1->priority < v2->priority ? -1 : v1->priority > v2->priority;
- }
- };
- for (InitHook *ihook = init_hooks; ihook; ihook = ihook->next)
- hv.push_back (ihook);
- stable_sort (hv.begin(), hv.end(), Sub::init_hook_cmp);
- for (std::vector<InitHook*>::iterator it = hv.begin(); it != hv.end(); it++)
- (*it)->hook();
-}
-
/* --- file utils --- */
namespace Path {
@@ -227,18 +347,111 @@
return path;
}
+static int
+errno_check_file (const char *file_name,
+ const char *mode)
+{
+ uint access_mask = 0, nac = 0;
+
+ if (strchr (mode, 'e')) /* exists */
+ nac++, access_mask |= F_OK;
+ if (strchr (mode, 'r')) /* readable */
+ nac++, access_mask |= R_OK;
+ if (strchr (mode, 'w')) /* writable */
+ nac++, access_mask |= W_OK;
+ bool check_exec = strchr (mode, 'x') != NULL;
+ if (check_exec) /* executable */
+ nac++, access_mask |= X_OK;
+
+ /* on some POSIX systems, X_OK may succeed for root without any
+ * executable bits set, so we also check via stat() below.
+ */
+ if (nac && access (file_name, access_mask) < 0)
+ return -errno;
+
+ bool check_file = strchr (mode, 'f') != NULL; /* open as file */
+ bool check_dir = strchr (mode, 'd') != NULL; /* open as directory */
+ bool check_link = strchr (mode, 'l') != NULL; /* open as link */
+ bool check_char = strchr (mode, 'c') != NULL; /* open as character device */
+ bool check_block = strchr (mode, 'b') != NULL; /* open as block device */
+ bool check_pipe = strchr (mode, 'p') != NULL; /* open as pipe */
+ bool check_socket = strchr (mode, 's') != NULL; /* open as socket */
+
+ if (check_exec || check_file || check_dir || check_link || check_char || check_block || check_pipe || check_socket)
+ {
+ struct stat st;
+
+ if (check_link)
+ {
+ if (lstat (file_name, &st) < 0)
+ return -errno;
+ }
+ else if (stat (file_name, &st) < 0)
+ return -errno;
+
+ if (0)
+ g_printerr ("file-check(\"%s\",\"%s\"): %s%s%s%s%s%s%s\n",
+ file_name, mode,
+ S_ISREG (st.st_mode) ? "f" : "",
+ S_ISDIR (st.st_mode) ? "d" : "",
+ S_ISLNK (st.st_mode) ? "l" : "",
+ S_ISCHR (st.st_mode) ? "c" : "",
+ S_ISBLK (st.st_mode) ? "b" : "",
+ S_ISFIFO (st.st_mode) ? "p" : "",
+ S_ISSOCK (st.st_mode) ? "s" : "");
+
+ if (S_ISDIR (st.st_mode) && (check_file || check_link || check_char || check_block || check_pipe))
+ return -EISDIR;
+ if (check_file && !S_ISREG (st.st_mode))
+ return -EINVAL;
+ if (check_dir && !S_ISDIR (st.st_mode))
+ return -ENOTDIR;
+ if (check_link && !S_ISLNK (st.st_mode))
+ return -EINVAL;
+ if (check_char && !S_ISCHR (st.st_mode))
+ return -ENODEV;
+ if (check_block && !S_ISBLK (st.st_mode))
+ return -ENOTBLK;
+ if (check_pipe && !S_ISFIFO (st.st_mode))
+ return -ENXIO;
+ if (check_socket && !S_ISSOCK (st.st_mode))
+ return -ENOTSOCK;
+ if (check_exec && !(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ return -EACCES; /* for root executable, any +x bit is good enough */
+ }
+
+ return 0;
+}
+
/**
* @param file possibly relative filename
* @param mode feature string
- * @return TRUE if @a file adhears to @a mode
+ * @return true if @a file adhears to @a mode
*
- * Perform various checks on @a file by calling birnet_file_check().
+ * Perform various checks on @a file and return whether all
+ * checks passed. On failure, errno is set appropriately, and
+ * FALSE is returned. Available features to be checked for are:
+ * @itemize
+ * @item e - @a file must exist
+ * @item r - @a file must be readable
+ * @item w - @a file must be writable
+ * @item x - @a file must be executable
+ * @item f - @a file must be a regular file
+ * @item d - @a file must be a directory
+ * @item l - @a file must be a symbolic link
+ * @item c - @a file must be a character device
+ * @item b - @a file must be a block device
+ * @item p - @a file must be a named pipe
+ * @item s - @a file must be a socket.
+ * @done
*/
bool
check (const String &file,
const String &mode)
{
- return file_check (file.c_str(), mode.c_str());
+ int err = file.size() && mode.size() ? errno_check_file (file.c_str(), mode.c_str()) : -EFAULT;
+ errno = err < 0 ? -err : 0;
+ return errno == 0;
}
/**
@@ -247,13 +460,27 @@
* @return TRUE if @a file1 and @a file2 are equal
*
* Check whether @a file1 and @a file2 are pointing to the same inode
- * in the same file system on the same device by calling birnet_file_equals().
+ * in the same file system on the same device.
*/
bool
equals (const String &file1,
const String &file2)
{
- return file_equals (file1.c_str(), file2.c_str());
+ if (!file1.size() || !file2.size())
+ return file1.size() == file2.size();
+ struct stat st1 = { 0, }, st2 = { 0, };
+ int err1 = 0, err2 = 0;
+ errno = 0;
+ if (stat (file1.c_str(), &st1) < 0 && stat (file1.c_str(), &st1) < 0)
+ err1 = errno;
+ errno = 0;
+ if (stat (file2.c_str(), &st2) < 0 && stat (file2.c_str(), &st2) < 0)
+ err2 = errno;
+ if (err1 || err2)
+ return err1 == err2;
+ return (st1.st_dev == st2.st_dev &&
+ st1.st_ino == st2.st_ino &&
+ st1.st_rdev == st2.st_rdev);
}
} // Path
@@ -303,7 +530,7 @@
}
static struct {
- Mutex mutex;
+ Mutex mutex;
std::map<Deletable*,Deletable::DeletionHook*> dmap;
} deletable_maps[19]; /* use prime size for hashing, sum up to roughly 1k (use 83 for 4k) */
@@ -489,4 +716,337 @@
clear_like_destructor();
}
+/* --- url handling --- */
+bool
+url_test_show (const char *url)
+{
+ static struct {
+ const char *prg, *arg1, *prefix, *postfix;
+ volatile bool disabled;
+ } www_browsers[] = {
+ /* program */ /* arg1 */ /* prefix+URL+postfix */
+ /* system browser launchers */
+ { "sensible-browser", NULL, "", "" },
+ { "x-www-browser", NULL, "", "" },
+ { "htmlview", NULL, "", "" },
+ /* portable browser launchers */
+ { "xdg-open", NULL, "", "" },
+#if 1
+ /* desktop browser launchers */
+ { "gnome-open", NULL, "", "" },
+ { "kfmclient", "openURL", "", "" },
+ { "gnome-moz-remote", "--newwin" "", "" },
+ /* specific browser programs */
+ { "firefox", NULL, "", "" },
+ { "mozilla-firefox", NULL, "", "" },
+ { "mozilla", NULL, "", "" },
+ { "opera", "-newwindow", "", "" },
+ { "konqueror", NULL, "", "" },
+#endif
+ /* above, we give system browser launchers precedence over xdg-open
+ * (especially the debian sensible-browser script), because xdg-open
+ * tends to exhibit bugs in desktop browser launchers still (e.g.
+ * gnome-open not honouring the users browser setting for file:///
+ * urls).
+ */
+ };
+ uint i;
+ for (i = 0; i < G_N_ELEMENTS (www_browsers); i++)
+ if (!www_browsers[i].disabled)
+ {
+ char *args[128] = { 0, };
+ uint n = 0;
+ args[n++] = (char*) www_browsers[i].prg;
+ if (www_browsers[i].arg1)
+ args[n++] = (char*) www_browsers[i].arg1;
+ char *string = g_strconcat (www_browsers[i].prefix, url, www_browsers[i].postfix, NULL);
+ args[n] = string;
+ GError *error = NULL;
+ bool success = g_spawn_async (NULL, /* cwd */
+ args,
+ NULL, /* envp */
+ G_SPAWN_SEARCH_PATH,
+ NULL, /* child_setup() */
+ NULL, /* user_data */
+ NULL, /* child_pid */
+ &error);
+ g_free (string);
+ // g_printerr ("show \"%s\": %s: %s\n", url, args[0], error ? error->message : "Ok");
+ g_clear_error (&error);
+ if (success)
+ return TRUE;
+ www_browsers[i].disabled = true;
+ }
+ /* reset disabled states if no browser could be found */
+ for (i = 0; i < G_N_ELEMENTS (www_browsers); i++)
+ www_browsers[i].disabled = false;
+ return false;
+}
+
+static void
+browser_launch_warning (const char *url)
+{
+ Msg::display (Msg::WARNING,
+ Msg::Title (_("Launch Web Browser")),
+ Msg::Text1 (_("Failed to launch a web browser executable")),
+ Msg::Text2 (_("No suitable web browser executable could be found to be executed and to display the URL: %s"), url),
+ Msg::Check (_("Show messages about web browser launch problems")));
+}
+
+void
+url_show (const char *url)
+{
+ bool success = url_test_show (url);
+ if (!success)
+ browser_launch_warning (url);
+}
+
+static void
+unlink_file_name (gpointer data)
+{
+ char *file_name = (char*) data;
+ while (unlink (file_name) < 0 && errno == EINTR);
+ g_free (file_name);
+}
+
+static const gchar*
+url_create_redirect (const char *url,
+ const char *url_title,
+ const char *cookie)
+{
+ const char *ver = "0.5";
+ gchar *tname = NULL;
+ gint fd = -1;
+ while (fd < 0)
+ {
+ g_free (tname);
+ tname = g_strdup_printf ("/tmp/Url%08X%04X.html", (int) lrand48(), getpid());
+ fd = open (tname, O_WRONLY | O_CREAT | O_EXCL, 00600);
+ if (fd < 0 && errno != EEXIST)
+ {
+ g_free (tname);
+ return NULL;
+ }
+ }
+ char *text = g_strdup_printf ("<!DOCTYPE HTML SYSTEM>\n"
+ "<html><head>\n"
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"
+ "<meta http-equiv=\"refresh\" content=\"0; URL=%s\">\n"
+ "<meta http-equiv=\"set-cookie\" content=\"%s\">\n"
+ "<title>%s</title>\n"
+ "</head><body>\n"
+ "<h1>%s</h1>\n"
+ "<b>Document Redirection</b><br>\n"
+ "Your browser is being redirected.\n"
+ "If it does not support automatic redirections, try <a href=\"%s\">%s</a>.\n"
+ "<hr>\n"
+ "<address>BirnetUrl/%s file redirect</address>\n"
+ "</body></html>\n",
+ url, cookie, url_title, url_title, url, url, ver);
+ int w, c, l = strlen (text);
+ do
+ w = write (fd, text, l);
+ while (w < 0 && errno == EINTR);
+ g_free (text);
+ do
+ c = close (fd);
+ while (c < 0 && errno == EINTR);
+ if (w != l || c < 0)
+ {
+ while (unlink (tname) < 0 && errno == EINTR)
+ {}
+ g_free (tname);
+ return NULL;
+ }
+ cleanup_add (60 * 1000, unlink_file_name, tname); /* free tname */
+ return tname;
+}
+
+bool
+url_test_show_with_cookie (const char *url,
+ const char *url_title,
+ const char *cookie)
+{
+ const char *redirect = url_create_redirect (url, url_title, cookie);
+ if (redirect)
+ return url_test_show (redirect);
+ else
+ return url_test_show (url);
+}
+
+void
+url_show_with_cookie (const char *url,
+ const char *url_title,
+ const char *cookie)
+{
+ bool success = url_test_show_with_cookie (url, url_title, cookie);
+ if (!success)
+ browser_launch_warning (url);
+}
+
+/* --- cleanups --- */
+typedef struct {
+ uint id;
+ GDestroyNotify handler;
+ void *data;
+} Cleanup;
+
+static Mutex cleanup_mutex;
+static GSList *cleanup_list = NULL;
+
+static void
+cleanup_exec_Lm (Cleanup *cleanup)
+{
+ cleanup_list = g_slist_remove (cleanup_list, cleanup);
+ g_source_remove (cleanup->id);
+ GDestroyNotify handler = cleanup->handler;
+ void *data = cleanup->data;
+ g_free (cleanup);
+ cleanup_mutex.unlock();
+ handler (data);
+ cleanup_mutex.lock();
+}
+
+/**
+ * Force all cleanup handlers (see birnet_cleanup_add()) to be immediately
+ * executed. This function should be called at program exit to execute
+ * cleanup handlers which have timeouts that have not yet expired.
+ */
+void
+cleanup_force_handlers (void)
+{
+ cleanup_mutex.lock();
+ while (cleanup_list)
+ cleanup_exec_Lm ((Cleanup*) cleanup_list->data);
+ cleanup_mutex.unlock();
+}
+
+static gboolean
+cleanup_exec (gpointer data)
+{
+ cleanup_mutex.lock();
+ cleanup_exec_Lm ((Cleanup*) data);
+ cleanup_mutex.unlock();
+ return FALSE;
+}
+
+/**
+ * @param timeout_ms timeout in milliseconds
+ * @param handler cleanup handler to run
+ * @param data cleanup handler data
+ *
+ * Register a cleanup handler, the @a handler is guaranteed to be run
+ * asyncronously (i.e. not from within cleanup_add()). The cleanup
+ * handler will be called as soon as @a timeout_ms has elapsed or
+ * cleanup_force_handlers() is called.
+ */
+uint
+cleanup_add (guint timeout_ms,
+ GDestroyNotify handler,
+ void *data)
+{
+ Cleanup *cleanup = g_new0 (Cleanup, 1);
+ cleanup->handler = handler;
+ cleanup->data = data;
+ cleanup->id = g_timeout_add (timeout_ms, cleanup_exec, cleanup);
+ cleanup_mutex.lock();
+ cleanup_list = g_slist_prepend (cleanup_list, cleanup);
+ cleanup_mutex.unlock();
+ return cleanup->id;
+}
+
+/* --- string utils --- */
+void
+memset4 (guint32 *mem,
+ guint32 filler,
+ guint length)
+{
+ BIRNET_STATIC_ASSERT (sizeof (*mem) == 4);
+ BIRNET_STATIC_ASSERT (sizeof (filler) == 4);
+ BIRNET_STATIC_ASSERT (sizeof (wchar_t) == 4);
+ wmemset ((wchar_t*) mem, filler, length);
+}
+
+/* --- memory utils --- */
+void*
+malloc_aligned (gsize total_size,
+ gsize alignment,
+ guint8 **free_pointer)
+{
+ uint8 *aligned_mem = (uint8*) g_malloc (total_size);
+ *free_pointer = aligned_mem;
+ if (!alignment || !(ptrdiff_t) aligned_mem % alignment)
+ return aligned_mem;
+ g_free (aligned_mem);
+ aligned_mem = (uint8*) g_malloc (total_size + alignment - 1);
+ *free_pointer = aligned_mem;
+ if ((ptrdiff_t) aligned_mem % alignment)
+ aligned_mem += alignment - (ptrdiff_t) aligned_mem % alignment;
+ return aligned_mem;
+}
+
+/* --- zintern support --- */
+#include <zlib.h>
+
+/**
+ * @param decompressed_size exact size of the decompressed data to be returned
+ * @param cdata compressed data block
+ * @param cdata_size exact size of the compressed data block
+ * @returns decompressed data block or NULL in low memory situations
+ *
+ * Decompress the data from @a cdata of length @a cdata_size into a newly
+ * allocated block of size @a decompressed_size which is returned.
+ * The returned block needs to be freed with g_free().
+ * This function is intended to decompress data which has been compressed
+ * with the birnet-zintern utility, so no errors should occour during
+ * decompression.
+ * Consequently, if any error occours during decompression or if the resulting
+ * data block is of a size other than @a decompressed_size, the program will
+ * abort with an appropriate error message.
+ * If not enough memory could be allocated for decompression, NULL is returned.
+ */
+uint8*
+zintern_decompress (unsigned int decompressed_size,
+ const unsigned char *cdata,
+ unsigned int cdata_size)
+{
+ uLongf dlen = decompressed_size;
+ uint64 len = dlen + 1;
+ uint8 *text = (uint8*) g_try_malloc (len);
+ if (!text)
+ return NULL; /* handle ENOMEM gracefully */
+
+ int64 result = uncompress (text, &dlen, cdata, cdata_size);
+ const char *err;
+ switch (result)
+ {
+ case Z_OK:
+ if (dlen == decompressed_size)
+ {
+ err = NULL;
+ break;
+ }
+ /* fall through */
+ case Z_DATA_ERROR:
+ err = "internal data corruption";
+ break;
+ case Z_MEM_ERROR:
+ err = "out of memory";
+ g_free (text);
+ return NULL; /* handle ENOMEM gracefully */
+ break;
+ case Z_BUF_ERROR:
+ err = "insufficient buffer size";
+ break;
+ default:
+ err = "unknown error";
+ break;
+ }
+ if (err)
+ g_error ("failed to decompress (%p, %u): %s", cdata, cdata_size, err);
+
+ text[dlen] = 0;
+ return text; /* success */
+}
+
} // Birnet
Modified: trunk/birnet/birnetutilsxx.hh
===================================================================
--- trunk/birnet/birnetutilsxx.hh 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/birnetutilsxx.hh 2006-10-06 21:53:52 UTC (rev 3939)
@@ -19,37 +19,24 @@
#ifndef __BIRNET_UTILS_XX_HH__
#define __BIRNET_UTILS_XX_HH__
-#include <birnet/birnetcore.h>
+#include <glib.h> // FIXME
+#include <birnet/birnetcdefs.h>
#include <string>
#include <vector>
#include <map>
namespace Birnet {
-/* --- convenient type shorthands --- */
-#ifdef _BIRNET_SOURCE_EXTENSIONS
-// using ::uint; // provided globally
-using ::uint8;
-using ::uint16;
-using ::uint32;
-using ::uint64;
-using ::int8;
-using ::int16;
-using ::int32;
-using ::int64;
-using ::unichar;
-#else /* !_BIRNET_SOURCE_EXTENSIONS */
-// typedef BirnetUInt uint; // provided globally
-typedef BirnetUInt8 uint8;
-typedef BirnetUInt16 uint16;
-typedef BirnetUInt32 uint32;
-typedef BirnetUInt64 uint64;
-typedef BirnetInt8 int8;
-typedef BirnetInt16 int16;
-typedef BirnetInt32 int32;
-typedef BirnetInt64 int64;
-typedef BirnetUniChar unichar;
-#endif
+/* --- short integer types --- */
+typedef BirnetUInt8 uint8;
+typedef BirnetUInt16 uint16;
+typedef BirnetUInt32 uint32;
+typedef BirnetUInt64 uint64;
+typedef BirnetInt8 int8;
+typedef BirnetInt16 int16;
+typedef BirnetInt32 int32;
+typedef BirnetInt64 int64;
+typedef BirnetUnichar unichar;
/* --- convenient stdc++ types --- */
typedef std::string String;
@@ -64,25 +51,58 @@
static String cxx_demangle (const char *mangled_identifier);
};
+/* --- implement assertion macros --- */
+#define BIRNET__RUNTIME_PROBLEM(ErrorWarningReturnAssertNotreach,domain,file,line,funcname,...) \
+ ::Birnet::birnet_runtime_problem (ErrorWarningReturnAssertNotreach, domain, file, line, funcname, __VA_ARGS__)
+void birnet_runtime_problem (char ewran_tag,
+ const char *domain,
+ const char *file,
+ int line,
+ const char *funcname,
+ const char *msgformat,
+ ...) BIRNET_PRINTF (6, 7);
+
/* --- private copy constructor and assignment operator --- */
#define BIRNET_PRIVATE_CLASS_COPY(Class) private: Class (const Class&); Class& operator= (const Class&);
#ifdef _BIRNET_SOURCE_EXTENSIONS
#define PRIVATE_CLASS_COPY BIRNET_PRIVATE_CLASS_COPY
#endif /* _BIRNET_SOURCE_EXTENSIONS */
-/* --- birnet_init() hook --- */
+/* --- initialization --- */
+typedef BirnetInitValue InitValue;
+typedef BirnetInitSettings InitSettings;
+extern const InitSettings *birnet_init_settings;
+void birnet_init (int *argcp,
+ char ***argvp,
+ const char *app_name,
+ InitValue ivalues[] = NULL);
+bool init_value_bool (InitValue *value);
+double init_value_double (InitValue *value);
+int64 init_value_int (InitValue *value);
+
+/* --- initialization hooks --- */
class InitHook {
- typedef void (*InitHookFunc) (void);
+ typedef void (*InitHookFunc) (void);
InitHook *next;
int priority;
InitHookFunc hook;
BIRNET_PRIVATE_CLASS_COPY (InitHook);
static void invoke_hooks (void);
public:
- explicit InitHook (InitHookFunc _func,
- int _priority = 0);
+ explicit InitHook (InitHookFunc _func,
+ int _priority = 0);
};
+/* --- assertions/warnings/errors --- */
+void raise_sigtrap ();
+#if (defined __i386__ || defined __x86_64__) && defined __GNUC__ && __GNUC__ >= 2
+extern inline void BREAKPOINT() { __asm__ __volatile__ ("int $03"); }
+#elif defined __alpha__ && !defined __osf__ && defined __GNUC__ && __GNUC__ >= 2
+extern inline void BREAKPOINT() { __asm__ __volatile__ ("bpt"); }
+#else /* !__i386__ && !__alpha__ */
+extern inline void BREAKPOINT() { raise_sigtrap(); }
+#endif /* __i386__ */
+
/* --- file/path functionality --- */
namespace Path {
const String dirname (const String &path);
@@ -103,6 +123,39 @@
const String &file2);
} // Path
+/* --- url handling --- */
+void url_show (const char *url);
+void url_show_with_cookie (const char *url,
+ const char *url_title,
+ const char *cookie);
+bool url_test_show (const char *url);
+bool url_test_show_with_cookie (const char *url,
+ const char *url_title,
+ const char *cookie);
+
+/* --- cleanup registration --- */
+uint cleanup_add (uint timeout_ms,
+ GDestroyNotify handler,
+ void *data);
+void cleanup_force_handlers (void);
+
+/* --- string utils --- */
+void memset4 (uint32 *mem,
+ uint32 filler,
+ uint length);
+/* --- memory utils --- */
+void* malloc_aligned (gsize total_size,
+ gsize alignment,
+ uint8 **free_pointer);
+
+/* --- C++ demangling --- */
+char* cxx_demangle (const char *mangled_identifier); /* in birnetutilsxx.cc */
+
+/* --- zintern support --- */
+uint8* zintern_decompress (unsigned int decompressed_size,
+ const unsigned char *cdata,
+ unsigned int cdata_size);
+
/* --- template errors --- */
namespace TEMPLATE_ERROR {
// to error out, call invalid_type<YourInvalidType>();
Modified: trunk/birnet/configure.inc
===================================================================
--- trunk/birnet/configure.inc 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/configure.inc 2006-10-06 21:53:52 UTC (rev 3939)
@@ -29,6 +29,25 @@
BIRNET_SIZEOF_SYS_TYPESH_UINT="$glib_cv_sizeof_sys_typesh_uint"
AC_SUBST(BIRNET_SIZEOF_SYS_TYPESH_UINT) dnl # for birnetconfig.h
+ dnl # --- OS/Win32 detection ---
+ dnl # needs AC_CANONICAL_HOST
+ test -z "$host" && {
+ missing_macro="AC""_CANONICAL_HOST"
+ AC_MSG_ERROR([configure failed to execute $missing_macro])
+ }
+ AC_MSG_CHECKING([for Win32])
+ case "$host" in
+ *-*-mingw*)
+ BIRNET_OS=WIN32
+ birnet_mingw=yes ;;
+ *)
+ BIRNET_OS=UNIX
+ birnet_mingw=no ;;
+ esac
+ AC_MSG_RESULT([$birnet_mingw])
+ AC_SUBST(BIRNET_OS)
+ AC_DEFINE_UNQUOTED(BIRNET_OS_$BIRNET_OS, "1", [Win32 detection])
+
dnl # --- sizeof threading structs ---
GLIB_SIZEOF([#include <pthread.h>], pthread_mutex_t, pth_mutex_t)
BIRNET_SIZEOF_PTH_MUTEX_T="$glib_cv_sizeof_pth_mutex_t"
Modified: trunk/birnet/tests/infotest.cc
===================================================================
--- trunk/birnet/tests/infotest.cc 2006-10-06 21:18:47 UTC (rev 3938)
+++ trunk/birnet/tests/infotest.cc 2006-10-06 21:53:52 UTC (rev 3939)
@@ -29,9 +29,9 @@
{
TSTART ("CpuInfo");
TOK();
- const BirnetCPUInfo *cpi = birnet_cpu_info ();
+ const BirnetCPUInfo *cpi = cpu_info ();
TASSERT (cpi != NULL);
- gchar *cps = birnet_cpu_info_string (cpi);
+ gchar *cps = cpu_info_string (cpi);
TASSERT (cps != NULL);
TPRINT ("%s", cps);
TOK();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]