]> granicus.if.org Git - strace/commitdiff
Open-code isprint(c) and isspace(c)
authorDenys Vlasenko <vda.linux@googlemail.com>
Wed, 6 Mar 2013 22:44:23 +0000 (23:44 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Wed, 6 Mar 2013 22:44:23 +0000 (23:44 +0100)
We don't call setlocale, thus we always use C locale.
But libc supports various other locales, and therefore
its ctype interface is general and at times inefficient.
For example, in glibc these macros result in function call,
whereas for e.g. isprint(c) just c >= ' ' && c <= 0x7e
suffices.

By open-coding ctype checks (we have only 4 of them)
we avoid function calls, we get smaller code:

   text    data     bss     dec     hex filename
 245127     680    5708  251515   3d67b strace_old
 245019     676    5708  251403   3d60b strace

and we don't link in ctype tables (beneficial for static builds).

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
defs.h
file.c
util.c

diff --git a/defs.h b/defs.h
index c20fcc6160f76c53351ca43438582e432c226660..bb4003f5a9a8b96ce6f8cabc3cb9058fba782f4a 100644 (file)
--- a/defs.h
+++ b/defs.h
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <ctype.h>
+/* Open-coding isprint(ch) et al proved more efficient than calling
+ * generalized libc interface. We don't *want* to do non-ASCII anyway.
+ */
+/* #include <ctype.h> */
 #include <string.h>
 #include <errno.h>
 #include <signal.h>
diff --git a/file.c b/file.c
index cfdd0bb98911323e845a83b1a1ee7115013d7063..2af14bffe4f9dea99697e2751947c8197f6dc887 100644 (file)
--- a/file.c
+++ b/file.c
@@ -2456,7 +2456,7 @@ print_xattr_val(struct tcb *tcp, int failed,
                        unsigned char *in = &buf[3 * size];
                        size_t i;
                        for (i = 0; i < size; ++i) {
-                               if (isprint(in[i]))
+                               if (in[i] >= ' ' && in[i] <= 0x7e)
                                        *out++ = in[i];
                                else {
 #define tohex(n) "0123456789abcdef"[n]
diff --git a/util.c b/util.c
index 0cc43feb9ddae9875fe15686cc7070ab5ae9edce..84ab00eb39a8a9042b51b6f261bf13de8fd4d4f6 100644 (file)
--- a/util.c
+++ b/util.c
@@ -400,7 +400,16 @@ string_quote(const char *instr, char *outstr, long len, int size)
                        /* Check for NUL-terminated string. */
                        if (c == eol)
                                break;
-                       if (!isprint(c) && !isspace(c)) {
+
+                       /* Force hex unless c is printable or whitespace */
+                       if (c > 0x7e) {
+                               usehex = 1;
+                               break;
+                       }
+                       /* In ASCII isspace is only these chars: "\t\n\v\f\r".
+                        * They happen to have ASCII codes 9,10,11,12,13.
+                        */
+                       if (c < ' ' && (unsigned)(c - 9) >= 5) {
                                usehex = 1;
                                break;
                        }
@@ -453,7 +462,7 @@ string_quote(const char *instr, char *outstr, long len, int size)
                                        *s++ = 'v';
                                        break;
                                default:
-                                       if (isprint(c))
+                                       if (c >= ' ' && c <= 0x7e)
                                                *s++ = c;
                                        else {
                                                /* Print \octal */