From 2d932586ceeb88f6691b08c80b741a3bffa04b3c Mon Sep 17 00:00:00 2001
From: root <root>
Date: Tue, 9 Mar 2010 08:46:16 +0000
Subject: ev_avoid_stdio

---
 Changes |  3 +++
 ev.c    | 60 +++++++++++++++++++++++++++++++++++++++++++++++-------------
 ev.pod  | 32 +++++++++++++++++++++++++-------
 3 files changed, 75 insertions(+), 20 deletions(-)

diff --git a/Changes b/Changes
index ed3fb38..57f6cb8 100644
--- a/Changes
+++ b/Changes
@@ -11,6 +11,9 @@ Revision history for libev, a high-performance and full-featured event loop.
           and analyzed by Aivars Kalvans).
         - improve header file compatibility of the standalone eventfd code
           in an obscure case.
+        - implement EV_AVOID_STDIO option.
+        - do not use sscanf to parse linux version number (smaller, faster,
+          no sscanf dependency).
 
 3.9  Thu Dec 31 07:59:59 CET 2009
 	- signalfd is no longer used by default and has to be requested
diff --git a/ev.c b/ev.c
index 2568f7b..280de7e 100644
--- a/ev.c
+++ b/ev.c
@@ -544,7 +544,15 @@ ev_syserr (const char *msg)
     syserr_cb (msg);
   else
     {
+#if EV_AVOID_STDIO
+      write (STDERR_FILENO, msg, strlen (msg));
+      write (STDERR_FILENO, ": ", 2);
+      msg = strerror (errno);
+      write (STDERR_FILENO, msg, strlen (msg));
+      write (STDERR_FILENO, "\n", 1);
+#else
       perror (msg);
+#endif
       abort ();
     }
 }
@@ -579,7 +587,12 @@ ev_realloc (void *ptr, long size)
 
   if (!ptr && size)
     {
+#if EV_AVOID_STDIO
+      write (STDERR_FILENO, "libev: memory allocation failed, aborting.",
+                    sizeof ("libev: memory allocation failed, aborting.") - 1);
+#else
       fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size);
+#endif
       abort ();
     }
 
@@ -2994,24 +3007,45 @@ infy_cb (EV_P_ ev_io *w, int revents)
     }
 }
 
-inline_size void
-check_2625 (EV_P)
+inline_size unsigned int
+ev_linux_version (void)
 {
-  /* kernels < 2.6.25 are borked
-   * http://www.ussg.indiana.edu/hypermail/linux/kernel/0711.3/1208.html
-   */
   struct utsname buf;
-  int major, minor, micro;
+  unsigned int v;
+  int i;
+  char *p = buf.release;
 
   if (uname (&buf))
-    return;
+    return 0;
 
-  if (sscanf (buf.release, "%d.%d.%d", &major, &minor, &micro) != 3)
-    return;
+  for (i = 3+1; --i; )
+    {
+      unsigned int c = 0;
 
-  if (major < 2
-      || (major == 2 && minor < 6)
-      || (major == 2 && minor == 6 && micro < 25))
+      for (;;)
+        {
+          if (*p >= '0' && *p <= '9')
+            c = c * 10 + *p++ - '0';
+          else
+            {
+              p += *p == '.';
+              break;
+            }
+        }
+
+      v = (v << 8) | c;
+    }
+
+  return v;
+}
+
+inline_size void
+ev_check_2625 (EV_P)
+{
+  /* kernels < 2.6.25 are borked
+   * http://www.ussg.indiana.edu/hypermail/linux/kernel/0711.3/1208.html
+   */
+  if (ev_linux_version () < 0x020619)
     return;
 
   fs_2625 = 1;
@@ -3036,7 +3070,7 @@ infy_init (EV_P)
 
   fs_fd = -1;
 
-  check_2625 (EV_A);
+  ev_check_2625 (EV_A);
 
   fs_fd = infy_newfd ();
 
diff --git a/ev.pod b/ev.pod
index b02defa..f13391d 100644
--- a/ev.pod
+++ b/ev.pod
@@ -3619,12 +3619,19 @@ For this of course you need the m4 file:
 =head2 PREPROCESSOR SYMBOLS/MACROS
 
 Libev can be configured via a variety of preprocessor symbols you have to
-define before including any of its files. The default in the absence of
-autoconf is documented for every option.
+define before including (or compiling) any of its files. The default in
+the absence of autoconf is documented for every option.
+
+Symbols marked with "(h)" do not change the ABI, and can have different
+values when compiling libev vs. including F<ev.h>, so it is permissible
+to redefine them before including F<ev.h> without breakign compatibility
+to a compiled library. All other symbols change the ABI, which means all
+users of libev and the libev code itself must be compiled with compatible
+settings.
 
 =over 4
 
-=item EV_STANDALONE
+=item EV_STANDALONE (h)
 
 Must always be C<1> if you do not use autoconf configuration, which
 keeps libev from including F<config.h>, and it also defines dummy
@@ -3784,24 +3791,24 @@ as well as for signal and thread safety in C<ev_async> watchers.
 In the absence of this define, libev will use C<sig_atomic_t volatile>
 (from F<signal.h>), which is usually good enough on most platforms.
 
-=item EV_H
+=item EV_H (h)
 
 The name of the F<ev.h> header file used to include it. The default if
 undefined is C<"ev.h"> in F<event.h>, F<ev.c> and F<ev++.h>. This can be
 used to virtually rename the F<ev.h> header file in case of conflicts.
 
-=item EV_CONFIG_H
+=item EV_CONFIG_H (h)
 
 If C<EV_STANDALONE> isn't C<1>, this variable can be used to override
 F<ev.c>'s idea of where to find the F<config.h> file, similarly to
 C<EV_H>, above.
 
-=item EV_EVENT_H
+=item EV_EVENT_H (h)
 
 Similarly to C<EV_H>, this macro can be used to override F<event.c>'s idea
 of how the F<event.h> header can be found, the default is C<"event.h">.
 
-=item EV_PROTOTYPES
+=item EV_PROTOTYPES (h)
 
 If defined to be C<0>, then F<ev.h> will not define any function
 prototypes, but still define all the structs and other symbols. This is
@@ -3883,6 +3890,17 @@ provide a bare-bones event library. See C<ev.h> for details on what parts
 of the API are still available, and do not complain if this subset changes
 over time.
 
+=item EV_AVOID_STDIO
+
+If this is set to C<1> at compiletime, then libev will avoid using stdio
+functions (printf, scanf, perror etc.). This will increase the codesize
+somewhat, but if your program doesn't otherwise depend on stdio and your
+libc allows it, this avoids linking in the stdio library which is quite
+big.
+
+Note that error messages might become less precise when this option is
+enabled.
+
 =item EV_NSIG
 
 The highest supported signal number, +1 (or, the number of
-- 
cgit v1.2.3