This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch zack/errno-prettyprint created. glibc-2.25-551-g09e65f0


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, zack/errno-prettyprint has been created
        at  09e65f085e8491db0ada73c558ffe8dc296ade47 (commit)

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=09e65f085e8491db0ada73c558ffe8dc296ade47

commit 09e65f085e8491db0ada73c558ffe8dc296ade47
Author: Zack Weinberg <zackw@panix.com>
Date:   Thu Jun 22 18:28:45 2017 -0400

    Add pretty-printer for errno.
    
    This patch adds the actual pretty-printer for errno.  I could have
    used Python's built-in errno module to get the symbolic names for the
    constants, but it seemed better to do something entirely under our
    control, so there's a .pysym file generated from errnos.texi, with a
    hook that allows the Hurd to add additional constants.  Then a .py
    module is generated from that plus errno.h in the usual manner; many
    thanks to the authors of the .pysym mechanism.
    
    There is also a test which verifies that the .py file (not the .pysym
    file) covers all of the constants defined in errno.h.
    
    hurd-add-errno-constants.awk has been manually tested, but the
    makefile logic that runs it has not been tested.
    
    	* stdlib/errno-printer.py: New pretty-printer.
    	* stdlib/test-errno-constants.py: New special test.
    	* stdlib/test-errno-printer.c, stdlib/test-errno-printer.py:
    	New pretty-printer test.
    	* stdlib/make-errno-constants.awk: New script to generate the
    	.pysym file needed by errno-printer.py.
    	* stdlib/Makefile: Install, run, and test all of the above, as
    	appropriate.
    
    	* sysdeps/mach/hurd/hurd-add-errno-constants.awk: New script to
    	add Mach/Hurd-specific errno constants to the .pysym file used by
    	stdlib/errno-printer.py.
    	* sysdeps/mach/hurd/Makefile: Hook hurd-add-errno-constants.awk
    	into the generation of that .pysym file.

diff --git a/stdlib/Makefile b/stdlib/Makefile
index 0314d59..3102546 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -149,6 +149,34 @@ ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)tst-fmtmsg.out
 endif
 
+ifdef PYTHON
+# Pretty-printer for errno.  The .pysym file is itself generated from
+# errnos.texi, and can be augmented by sysdeps Makefiles, primarily for
+# the sake of the Hurd, which has a bunch of extra error constants.
+pretty-printers := errno-printer.py
+tests-printers := test-errno-printer
+gen-py-const-headers := errno_constants.pysym
+vpath %.pysym $(objpfx)
+
+define sysd-add-errno-constants
+:
+endef
+$(objpfx)errno_constants.pysym: make-errno-constants.awk \
+				$(..)manual/errno.texi
+	($(AWK) -f make-errno-constants.awk $(..)manual/errno.texi; \
+	$(sysd-add-errno-constants)) > $@T
+	mv -f $@T $@
+
+# We must specify both CFLAGS and CPPFLAGS to override any
+# compiler options the user might have provided that conflict
+# with what we need e.g. user specifies CPPFLAGS with -O2 and
+# we need -O0.
+CFLAGS-test-errno-printer.c := $(CFLAGS-printers-tests)
+CPPFLAGS-test-errno-printer.c := $(CFLAGS-printers-tests)
+
+tests-special += $(objpfx)test-errno-constants.out
+endif
+
 include ../Rules
 
 ifeq ($(run-built-tests),yes)
@@ -220,3 +248,13 @@ $(objpfx)tst-setcontext3.out: tst-setcontext3.sh $(objpfx)tst-setcontext3
 	$(evaluate-test)
 
 $(objpfx)tst-makecontext: $(libdl)
+
+# Note: errno_constants.py depends on errno.h and everything it
+# includes, as well as on errno_constants.pysym, so we don't need to
+# specify that this test also depends on both.
+$(objpfx)test-errno-constants.out: \
+		test-errno-constants.py $(objpfx)errno_constants.py
+	$(PYTHON) $< $(objpfx) $(CC) $(CFLAGS) $(CPPFLAGS) > $@; \
+	$(evaluate-test)
+
+libof-test-errno-constants = testsuite
diff --git a/stdlib/errno-printer.py b/stdlib/errno-printer.py
new file mode 100644
index 0000000..aa09c78
--- /dev/null
+++ b/stdlib/errno-printer.py
@@ -0,0 +1,105 @@
+# Pretty printer for errno.
+# Copyright (C) 2016-2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C 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.1 of the License, or (at your option) any later version.
+#
+# The GNU C 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 the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+"""This file contains the gdb pretty printers for the following types:
+
+    * __error_t (the type of 'errno')
+    * error_t   (cast any 'int' to 'error_t' to print it like an errno value)
+
+You can check which printers are registered and enabled by issuing the
+'info pretty-printer' gdb command.  Printers should trigger automatically when
+trying to print a variable of one of the types mentioned above.
+"""
+
+
+import gdb
+import gdb.printing
+import errno_constants
+
+
+def make_errno_reverse_mapping():
+    """Construct a reverse mapping from errno values to symbolic names.
+       The result is a dictionary indexed by integers, not a list,
+       because errno values are not necessarily contiguous.
+    """
+
+    # Certain errno symbols are allowed to have the same numeric value.
+    # If they do, one of them (whichever one is in POSIX, or if both or
+    # neither are, the shortest) is selected as the preferred name.
+    # This map goes from non-preferred name(s) to preferred name.
+    permitted_collisions = {
+        "EDEADLOCK":   "EDEADLK",
+        "EOPNOTSUPP":  "ENOTSUP",
+        "EWOULDBLOCK": "EAGAIN",
+    }
+
+    errno_names = { 0: "Success" }
+    for name in dir(errno_constants):
+        if name[0] == 'E':
+            number = getattr(errno_constants, name)
+            other = errno_names.get(number)
+            if other is None:
+                errno_names[number] = name
+            else:
+                p1 = permitted_collisions.get(name)
+                p2 = permitted_collisions.get(other)
+                if p1 is not None and p1 == other:
+                    pass # the value in errno_names is already what we want
+                elif p2 is not None and p2 == name:
+                    errno_names[number] = name
+                else:
+                    raise RuntimeError(
+                        "errno value collision: {} = {}, {}"
+                        .format(number, name, errno_names[number]))
+
+    return errno_names
+
+
+errno_names = make_errno_reverse_mapping()
+
+
+class ErrnoPrinter(object):
+    """Pretty printer for errno values."""
+
+    def __init__(self, val):
+        self._val = int(val)
+
+    def to_string(self):
+        """gdb API function.
+
+        This is called from gdb when we try to print an error_t.
+        """
+        if self._val in errno_names:
+            return "{:d} ({})".format(self._val, errno_names[self._val])
+        else:
+            return "{:d}".format(self._val)
+
+
+def register(objfile):
+    """Register pretty printers for the current objfile."""
+
+    printer = gdb.printing.RegexpCollectionPrettyPrinter("glibc-errno")
+    printer.add_printer('error_t', r'^(?:__)?error_t', ErrnoPrinter)
+
+    if objfile == None:
+        objfile = gdb
+
+    gdb.printing.register_pretty_printer(objfile, printer)
+
+
+register(gdb.current_objfile())
diff --git a/stdlib/make-errno-constants.awk b/stdlib/make-errno-constants.awk
new file mode 100644
index 0000000..32344dc
--- /dev/null
+++ b/stdlib/make-errno-constants.awk
@@ -0,0 +1,66 @@
+# Copyright (C) 2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C 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.1 of the License, or (at your option) any later version.
+
+# The GNU C 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 the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+# Generate errno_constants.pysym from errno.texi.
+# errno.texi contains lines like:
+# @errno{ENOSYS, 123, Function not implemented}
+# The number is only relevant for the Hurd.
+
+BEGIN {
+    print "#include <errno.h>"
+    print ""
+    print "-- Errno constants"
+
+    # Some error constants do not exist on all supported operating systems.
+    # FIXME: Encode this information in errno.texi.
+    ## (Sometimes) two names for the same number
+    optional["EDEADLOCK"]	= 1
+    optional["EDEADLK"]		= 1
+    optional["EOPNOTSUPP"]	= 1
+    optional["ENOTSUP"]		= 1
+    optional["EWOULDBLOCK"]	= 1
+    optional["EAGAIN"]		= 1
+    ## BSD-specific
+    optional["EAUTH"]		= 1
+    optional["EBADRPC"]		= 1
+    optional["EFTYPE"]		= 1
+    optional["ENEEDAUTH"]	= 1
+    optional["EPROCLIM"]	= 1
+    optional["EPROCUNAVAIL"]	= 1
+    optional["EPROGMISMATCH"]	= 1
+    optional["EPROGUNAVAIL"]	= 1
+    optional["ERPCMISMATCH"]	= 1
+    ## GNU-specific
+    optional["EBACKGROUND"]	= 1
+    optional["ED"]		= 1
+    optional["EDIED"]		= 1
+    optional["EGRATUITOUS"]	= 1
+    optional["EGREGIOUS"]	= 1
+    optional["EIEIO"]		= 1
+}
+
+/^@errno\{/ {
+    e = substr($1, 8, length($1)-8)
+    if (e in optional)
+      {
+	print "#ifdef", e
+	print e
+	print "#endif"
+      }
+    else
+	print e
+}
diff --git a/stdlib/test-errno-constants.py b/stdlib/test-errno-constants.py
new file mode 100644
index 0000000..a79df97
--- /dev/null
+++ b/stdlib/test-errno-constants.py
@@ -0,0 +1,58 @@
+# Test that errno_constants.py includes every error number defined by errno.h.
+# Copyright (C) 2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C 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.1 of the License, or (at your option) any later version.
+#
+# The GNU C 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 the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+# Usage: test-errno-constants.py $(common-objpfx)stdlib $(CC) $(CFLAGS) $(CPPFLAGS)
+
+import os
+import sys
+import subprocess
+
+sys.path.append(sys.argv[1])
+import errno_constants
+
+def main():
+    cc_cmd = sys.argv[2:]
+    cc_cmd.extend(["-E", "-dM", "-xc", "-"])
+    cc_proc = subprocess.Popen(cc_cmd,
+                               stdin=subprocess.PIPE,
+                               stdout=subprocess.PIPE)
+    cc_proc.stdin.write(b"#define _GNU_SOURCE\n"
+                       b"#include <errno.h>\n")
+    cc_proc.stdin.close()
+
+    cc_output = cc_proc.stdout.read()
+    status = cc_proc.wait()
+    if status:
+        sys.stderr.write("{}\nunsuccessful exit, status {:04x}"
+                         .format(" ".join(cc_cmd), status))
+        sys.exit(1)
+
+    ok = True
+    for line in cc_output.decode("utf-8").splitlines():
+        if not line.startswith("#define E"):
+            continue
+        emacro = line.split()[1]
+        if not hasattr(errno_constants, emacro):
+            if ok:
+                sys.stderr.write("*** Missing constants:\n")
+                ok = False
+            sys.stderr.write(emacro + "\n")
+
+    sys.exit(0 if ok else 1)
+
+main()
diff --git a/stdlib/test-errno-printer.c b/stdlib/test-errno-printer.c
new file mode 100644
index 0000000..da2345f
--- /dev/null
+++ b/stdlib/test-errno-printer.c
@@ -0,0 +1,43 @@
+/* Helper program for testing the errno pretty-printer.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C 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.1 of the License, or (at your option) any later version.
+
+   The GNU C 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 the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define _GNU_SOURCE 1
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#define PASS 0
+#define FAIL 1
+
+const error_t array_of_error_t[3] = { 0, ERANGE, -2 };
+
+__thread int ensure_gdb_can_read_thread_variables = 0;
+
+int
+main (void)
+{
+  int result = PASS;
+  errno = array_of_error_t[0];
+  unsigned long x = strtoul("9999999999999999999999999999999999999", 0, 10);
+  if (x != ULONG_MAX)
+    result = FAIL;
+  if (errno != ERANGE)
+    result = FAIL;
+  errno = -2; /* Break: test errno 2 */
+  return result;
+}
diff --git a/stdlib/test-errno-printer.py b/stdlib/test-errno-printer.py
new file mode 100644
index 0000000..b55ee08
--- /dev/null
+++ b/stdlib/test-errno-printer.py
@@ -0,0 +1,71 @@
+# Test for the errno pretty-printer.
+# Copyright (C) 2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C 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.1 of the License, or (at your option) any later version.
+#
+# The GNU C 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 the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+import sys
+
+from test_printers_common import *
+
+test_source = sys.argv[1]
+test_bin = sys.argv[2]
+printer_files = sys.argv[3:]
+printer_names = ['global glibc-errno']
+
+try:
+    init_test(test_bin, printer_files, printer_names)
+    go_to_main()
+
+    # All supported versions of gdb do run the pretty-printer on an
+    # _array_ of error_t.
+    test_printer('array_of_error_t',
+                 r'= \{0 \(Success\), \d+ \(ERANGE\), -2\}', is_ptr=False)
+
+    # Some versions of gdb don't run the pretty-printer on a _scalar_
+    # whose type is error_t.  If we have such a gdb, the test is
+    # unsupported.
+    test('print (error_t) 0',
+         pattern             = r'= 0 \(Success\)$',
+         unsupported_pattern = r'= 0$')
+
+    # Some versions of gdb don't support reading thread-specific variables;
+    # these versions may also have trouble reading errno.
+    test('print ensure_gdb_can_read_thread_variables',
+         pattern             = r'= 0$',
+         unsupported_pattern = r'Cannot find thread-local')
+
+    next_cmd()
+    next_cmd()
+    test_printer('errno', r'0 (Success)', is_ptr=False)
+    next_cmd()
+    test_printer('errno', r'\d+ (ERANGE)', is_ptr=False)
+
+    break_at(test_source, 'test errno 2', is_ptr=False)
+    continue_cmd()
+    next_cmd()
+    test_printer('errno', r'-2', is_ptr=False)
+
+    continue_cmd() # Exit
+
+except (NoLineError, pexpect.TIMEOUT) as exception:
+    print('Error: {0}'.format(exception))
+    result = FAIL
+
+else:
+    print('Test succeeded.')
+    result = PASS
+
+exit(result)
diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile
index 13bdf5c..5171425 100644
--- a/sysdeps/mach/hurd/Makefile
+++ b/sysdeps/mach/hurd/Makefile
@@ -98,6 +98,16 @@ $(common-objpfx)stamp-errnos: $(hurd)/errnos.awk $(errno.texinfo) \
 	touch $@
 
 common-generated += errnos.d stamp-errnos
+
+# Augmentations to the errno pretty-printer.
+ifeq ($(subdir),stdlib)
+define sysd-add-errno-constants
+$(AWK) -f $(hurd)/hurd-add-errno-constants.awk $(mach-errnos-deps)
+endef
+$(objpfx)errno_constants.pysym: \
+    $(hurd)/hurd-add-errno-constants.awk $(mach-errnos-deps)
+endif
+
 
 # We install the real libc.a as libcrt.a and as libc.a we install a linker
 # script which does -( -lcrt -lmachuser -lhurduser -).
diff --git a/sysdeps/mach/hurd/hurd-add-errno-constants.awk b/sysdeps/mach/hurd/hurd-add-errno-constants.awk
new file mode 100644
index 0000000..0d51766
--- /dev/null
+++ b/sysdeps/mach/hurd/hurd-add-errno-constants.awk
@@ -0,0 +1,80 @@
+# Add Hurd-specific constants to errno_constants.pysym.
+# Copyright (C) 2017 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C 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.1 of the License, or (at your option) any later version.
+
+# The GNU C 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 the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+# On the Hurd, errno.h defines E-constants corresponding to a number of
+# Mach low-level errors.  Add these to the set of values recognized by
+# stdlib/errno-printer.py.  This script must be kept in sync with errnos.awk.
+
+BEGIN {
+  in_mach_errors = "";
+  in_mig_errors = 0;
+  in_device_errors = 0;
+}
+
+function emit_subhead()
+{
+  header = FILENAME;
+  sub(/.*include\//, "", header);
+  printf("\n-- Errors from <%s>\n", header);
+}
+
+NF == 3 && $1 == "#define" && $2 == "MACH_SEND_IN_PROGRESS" \
+  {
+    in_mach_errors = FILENAME;
+    emit_subhead();
+  }
+NF == 3 && $1 == "#define" && $2 == "KERN_SUCCESS" \
+  {
+    in_mach_errors = FILENAME;
+    emit_subhead();
+    next;
+  }
+in_mach_errors != "" && $2 == "MACH_IPC_COMPAT" \
+  {
+    in_mach_errors = "";
+    next;
+  }
+
+$1 == "#define" && $2 == "_MACH_MIG_ERRORS_H_" \
+  {
+    in_mig_errors = 1;
+    emit_subhead();
+    next;
+  }
+in_mig_errors && $1 == "#endif" && $3 == "_MACH_MIG_ERRORS_H_" \
+  {
+    in_mig_errors = 0;
+  }
+
+$1 == "#define" && $2 == "D_SUCCESS" \
+  {
+    in_device_errors = 1;
+    emit_subhead();
+    next;
+  }
+in_device_errors && $1 == "#endif" \
+  {
+    in_device_errors = 0;
+  }
+
+(in_mach_errors == FILENAME && NF == 3 && $1 == "#define") || \
+(in_mig_errors && $1 == "#define" && $3 <= -300) || \
+(in_device_errors && $1 == "#define" && $2 ~ /D_/ && NF > 3) \
+  {
+    print "E" $2;
+  }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=bf7aa82eab0f1f9c78d39cf57a3f6b25eefc47c1

commit bf7aa82eab0f1f9c78d39cf57a3f6b25eefc47c1
Author: Zack Weinberg <zackw@panix.com>
Date:   Thu Jun 22 18:06:15 2017 -0400

    Make error_t always int; make __errno_location return an __error_t.
    
    error_t is a Hurdism whose purpose, as far as I know, is to make it so
    you can get GDB to tell you the E-constant corresponding to the
    current value of errno by typing 'p (error_t) errno'.  I tried to
    generalize this to all platforms a few weeks ago and it was suggested
    to me that this is maybe a job for a GDB pretty-printer, instead.
    This patch clears the ground for that, by removing the Hurd-specific
    definition of error_t.
    
    error_t is also used to make the return values of a few GNU extension
    functions (in argp.h and argz.h) a little more self-documenting, so it
    can't completely go away, and it will be useful to be able to write
    'p (error_t) err' where err is some ordinary int variable that happens
    to have an errno value stashed in it.  So now stdlib/errno.h defines it
    and it's always just a typedef for 'int'.
    
    This patch also changes all definitions of __errno_location and the
    underlying thread-local errno to have type __error_t instead of int.
    __error_t is also just a typedef for int, but this is how we will cue
    the GDB pretty-printer to print errno specially.  I believe that this
    does not have any standards-compliance consequences, because it's just
    a typedef for int.  This part of the change doesn't make sense in the
    absence of the pretty-printer itself, but this split-up seemed more
    useful to reviewers.
    
    	* stdlib/errno.h (__error_t): New type (typedef as int).
    	(__errno_location): Declare as returning __error_t.
    	(error_t): Typedef as __error_t, if not already defined.
    
    	* csu/errno-loc.c, csu/errno.c, include/errno.h
    	* sysdeps/mach/hurd/dl-sysdep.c, sysdeps/mach/hurd/errno-loc.c:
    	Change type of errno, __libc_errno, and rtld_errno, and
    	return type of __errno_location to __error_t.
    
    	* sysdeps/mach/hudr/errnos.awk: Do not emit enum __error_t_codes
    	or a definition of error_t.
    	* sysdeps/mach/hurd/bits/errno.h: Regenerate.
    	* sysdeps/mach/hurd/errno.c: Delete file.
    	* bits/errno.h: Update commentary.

diff --git a/bits/errno.h b/bits/errno.h
index 1118071..48b0834 100644
--- a/bits/errno.h
+++ b/bits/errno.h
@@ -37,14 +37,13 @@
    expand to "integer constant expressions with type int, positive
    values, and suitable for use in #if directives".  Moreover, all of
    their names must begin with a capital E, followed immediately by
-   either another capital letter, or a digit.  It is OK to define
-   macros that are not error constants, but only in the implementation
-   namespace.
+   either another capital letter, or a digit.
 
    errno.h is sometimes included from assembly language.  Therefore,
-   when __ASSEMBLER__ is defined, bits/errno.h may only define macros;
-   it may not make any other kind of C declaration or definition.
-   Also, the error constants should, if at all possible, expand to
-   simple decimal or hexadecimal numbers.  */
+   bits/errno.h may only define macros; it may not make any other kind
+   of C declaration or definition.  Also, the error constants should,
+   if at all possible, expand to simple decimal or hexadecimal
+   numbers.  It is OK to define macros that are not error constants,
+   but only in the implementation namespace.  */
 
 #endif /* bits/errno.h.  */
diff --git a/csu/errno-loc.c b/csu/errno-loc.c
index ddc4e14..3f3e8f0 100644
--- a/csu/errno-loc.c
+++ b/csu/errno-loc.c
@@ -20,7 +20,7 @@
 #include <errno.h>
 #include <tls.h>
 
-int *
+__error_t *
 __errno_location (void)
 {
   return &errno;
diff --git a/csu/errno.c b/csu/errno.c
index 8b2e348..ae5b976 100644
--- a/csu/errno.c
+++ b/csu/errno.c
@@ -28,8 +28,8 @@ int rtld_errno attribute_hidden;
 
 #else
 
-__thread int errno;
-extern __thread int __libc_errno __attribute__ ((alias ("errno")))
+__thread __error_t errno;
+extern __thread __error_t __libc_errno __attribute__ ((alias ("errno")))
   attribute_hidden;
 
 #endif
diff --git a/include/errno.h b/include/errno.h
index 3c3d228..da034bd 100644
--- a/include/errno.h
+++ b/include/errno.h
@@ -18,7 +18,7 @@
 
 #  undef  errno
 #  define errno rtld_errno
-extern int rtld_errno attribute_hidden;
+extern __error_t rtld_errno attribute_hidden;
 
 # elif IS_IN_LIB
 
@@ -30,13 +30,13 @@ extern int rtld_errno attribute_hidden;
 #  else
 #   define errno errno		/* For #ifndef errno tests.  */
 #  endif
-extern __thread int errno attribute_tls_model_ie;
+extern __thread __error_t errno attribute_tls_model_ie;
 
 # endif	/* IS_IN_LIB */
 
 # define __set_errno(val) (errno = (val))
 
-extern int *__errno_location (void) __THROW __attribute_const__
+extern __error_t *__errno_location (void) __THROW __attribute_const__
 #  if RTLD_PRIVATE_ERRNO
      attribute_hidden
 #  endif
diff --git a/stdlib/errno.h b/stdlib/errno.h
index fe08365..c5ba522 100644
--- a/stdlib/errno.h
+++ b/stdlib/errno.h
@@ -33,8 +33,12 @@
 
 __BEGIN_DECLS
 
+/* This type cues the GDB pretty-printer for errno (errno-printer.py)
+   to show a symbolic name for the error.  */
+typedef int __error_t;
+
 /* The error code set by various library functions.  */
-extern int *__errno_location (void) __THROW __attribute_const__;
+extern __error_t *__errno_location (void) __THROW __attribute_const__;
 # define errno (*__errno_location ())
 
 # ifdef __USE_GNU
@@ -45,11 +49,11 @@ extern int *__errno_location (void) __THROW __attribute_const__;
 extern char *program_invocation_name;
 extern char *program_invocation_short_name;
 
-/* bits/errno.h may have defined this type.  If it didn't, provide a
-   fallback definition.  */
+/* User namespace version of __error_t.  This is used to make the return
+   values of certain GNU extension functions more self-documenting.  */
 #  ifndef __error_t_defined
 #   define __error_t_defined 1
-typedef int error_t;
+typedef __error_t error_t;
 #  endif
 
 # endif /* __USE_GNU */
diff --git a/sysdeps/mach/hurd/bits/errno.h b/sysdeps/mach/hurd/bits/errno.h
index f0a11af..655d9c8 100644
--- a/sysdeps/mach/hurd/bits/errno.h
+++ b/sysdeps/mach/hurd/bits/errno.h
@@ -13,323 +13,110 @@
 # error "Never include <bits/errno.h> directly; use <errno.h> instead."
 #endif
 
-#ifndef __ASSEMBLER__
-
-enum __error_t_codes
-{
-  /* The value zero always means success and it is perfectly fine
-     for code to use 0 explicitly (or implicitly, e.g. via Boolean
-     coercion.)  Having an enum entry for zero both makes the
-     debugger print the name for error_t-typed zero values, and
-     prevents the compiler from issuing warnings about 'case 0:'
-     in a switch on an error_t-typed value.  */
-  ESUCCESS                       = 0,
-
-  /* The Hurd uses Mach error system 0x10, subsystem 0. */
-  EPERM                          = 0x40000001,	/* Operation not permitted */
-  ENOENT                         = 0x40000002,	/* No such file or directory */
-  ESRCH                          = 0x40000003,	/* No such process */
-  EINTR                          = 0x40000004,	/* Interrupted system call */
-  EIO                            = 0x40000005,	/* Input/output error */
-  ENXIO                          = 0x40000006,	/* No such device or address */
-  E2BIG                          = 0x40000007,	/* Argument list too long */
-  ENOEXEC                        = 0x40000008,	/* Exec format error */
-  EBADF                          = 0x40000009,	/* Bad file descriptor */
-  ECHILD                         = 0x4000000a,	/* No child processes */
-  EDEADLK                        = 0x4000000b,	/* Resource deadlock avoided */
-  ENOMEM                         = 0x4000000c,	/* Cannot allocate memory */
-  EACCES                         = 0x4000000d,	/* Permission denied */
-  EFAULT                         = 0x4000000e,	/* Bad address */
-  ENOTBLK                        = 0x4000000f,	/* Block device required */
-  EBUSY                          = 0x40000010,	/* Device or resource busy */
-  EEXIST                         = 0x40000011,	/* File exists */
-  EXDEV                          = 0x40000012,	/* Invalid cross-device link */
-  ENODEV                         = 0x40000013,	/* No such device */
-  ENOTDIR                        = 0x40000014,	/* Not a directory */
-  EISDIR                         = 0x40000015,	/* Is a directory */
-  EINVAL                         = 0x40000016,	/* Invalid argument */
-  EMFILE                         = 0x40000018,	/* Too many open files */
-  ENFILE                         = 0x40000017,	/* Too many open files in system */
-  ENOTTY                         = 0x40000019,	/* Inappropriate ioctl for device */
-  ETXTBSY                        = 0x4000001a,	/* Text file busy */
-  EFBIG                          = 0x4000001b,	/* File too large */
-  ENOSPC                         = 0x4000001c,	/* No space left on device */
-  ESPIPE                         = 0x4000001d,	/* Illegal seek */
-  EROFS                          = 0x4000001e,	/* Read-only file system */
-  EMLINK                         = 0x4000001f,	/* Too many links */
-  EPIPE                          = 0x40000020,	/* Broken pipe */
-  EDOM                           = 0x40000021,	/* Numerical argument out of domain */
-  ERANGE                         = 0x40000022,	/* Numerical result out of range */
-  EAGAIN                         = 0x40000023,	/* Resource temporarily unavailable */
-  EINPROGRESS                    = 0x40000024,	/* Operation now in progress */
-  EALREADY                       = 0x40000025,	/* Operation already in progress */
-  ENOTSOCK                       = 0x40000026,	/* Socket operation on non-socket */
-  EMSGSIZE                       = 0x40000028,	/* Message too long */
-  EPROTOTYPE                     = 0x40000029,	/* Protocol wrong type for socket */
-  ENOPROTOOPT                    = 0x4000002a,	/* Protocol not available */
-  EPROTONOSUPPORT                = 0x4000002b,	/* Protocol not supported */
-  ESOCKTNOSUPPORT                = 0x4000002c,	/* Socket type not supported */
-  EOPNOTSUPP                     = 0x4000002d,	/* Operation not supported */
-  EPFNOSUPPORT                   = 0x4000002e,	/* Protocol family not supported */
-  EAFNOSUPPORT                   = 0x4000002f,	/* Address family not supported by protocol */
-  EADDRINUSE                     = 0x40000030,	/* Address already in use */
-  EADDRNOTAVAIL                  = 0x40000031,	/* Cannot assign requested address */
-  ENETDOWN                       = 0x40000032,	/* Network is down */
-  ENETUNREACH                    = 0x40000033,	/* Network is unreachable */
-  ENETRESET                      = 0x40000034,	/* Network dropped connection on reset */
-  ECONNABORTED                   = 0x40000035,	/* Software caused connection abort */
-  ECONNRESET                     = 0x40000036,	/* Connection reset by peer */
-  ENOBUFS                        = 0x40000037,	/* No buffer space available */
-  EISCONN                        = 0x40000038,	/* Transport endpoint is already connected */
-  ENOTCONN                       = 0x40000039,	/* Transport endpoint is not connected */
-  EDESTADDRREQ                   = 0x40000027,	/* Destination address required */
-  ESHUTDOWN                      = 0x4000003a,	/* Cannot send after transport endpoint shutdown */
-  ETOOMANYREFS                   = 0x4000003b,	/* Too many references: cannot splice */
-  ETIMEDOUT                      = 0x4000003c,	/* Connection timed out */
-  ECONNREFUSED                   = 0x4000003d,	/* Connection refused */
-  ELOOP                          = 0x4000003e,	/* Too many levels of symbolic links */
-  ENAMETOOLONG                   = 0x4000003f,	/* File name too long */
-  EHOSTDOWN                      = 0x40000040,	/* Host is down */
-  EHOSTUNREACH                   = 0x40000041,	/* No route to host */
-  ENOTEMPTY                      = 0x40000042,	/* Directory not empty */
-  EPROCLIM                       = 0x40000043,	/* Too many processes */
-  EUSERS                         = 0x40000044,	/* Too many users */
-  EDQUOT                         = 0x40000045,	/* Disk quota exceeded */
-  ESTALE                         = 0x40000046,	/* Stale file handle */
-  EREMOTE                        = 0x40000047,	/* Object is remote */
-  EBADRPC                        = 0x40000048,	/* RPC struct is bad */
-  ERPCMISMATCH                   = 0x40000049,	/* RPC version wrong */
-  EPROGUNAVAIL                   = 0x4000004a,	/* RPC program not available */
-  EPROGMISMATCH                  = 0x4000004b,	/* RPC program version wrong */
-  EPROCUNAVAIL                   = 0x4000004c,	/* RPC bad procedure for program */
-  ENOLCK                         = 0x4000004d,	/* No locks available */
-  EFTYPE                         = 0x4000004f,	/* Inappropriate file type or format */
-  EAUTH                          = 0x40000050,	/* Authentication error */
-  ENEEDAUTH                      = 0x40000051,	/* Need authenticator */
-  ENOSYS                         = 0x4000004e,	/* Function not implemented */
-  ENOTSUP                        = 0x40000076,	/* Not supported */
-  EILSEQ                         = 0x4000006a,	/* Invalid or incomplete multibyte or wide character */
-  EBACKGROUND                    = 0x40000064,	/* Inappropriate operation for background process */
-  EDIED                          = 0x40000065,	/* Translator died */
-  ED                             = 0x40000066,	/* ? */
-  EGREGIOUS                      = 0x40000067,	/* You really blew it this time */
-  EIEIO                          = 0x40000068,	/* Computer bought the farm */
-  EGRATUITOUS                    = 0x40000069,	/* Gratuitous error */
-  EBADMSG                        = 0x4000006b,	/* Bad message */
-  EIDRM                          = 0x4000006c,	/* Identifier removed */
-  EMULTIHOP                      = 0x4000006d,	/* Multihop attempted */
-  ENODATA                        = 0x4000006e,	/* No data available */
-  ENOLINK                        = 0x4000006f,	/* Link has been severed */
-  ENOMSG                         = 0x40000070,	/* No message of desired type */
-  ENOSR                          = 0x40000071,	/* Out of streams resources */
-  ENOSTR                         = 0x40000072,	/* Device not a stream */
-  EOVERFLOW                      = 0x40000073,	/* Value too large for defined data type */
-  EPROTO                         = 0x40000074,	/* Protocol error */
-  ETIME                          = 0x40000075,	/* Timer expired */
-  ECANCELED                      = 0x40000077,	/* Operation canceled */
-
-/* Errors from <mach/message.h>.  */
-  EMACH_SEND_IN_PROGRESS         = 0x10000001,
-  EMACH_SEND_INVALID_DATA        = 0x10000002,
-  EMACH_SEND_INVALID_DEST        = 0x10000003,
-  EMACH_SEND_TIMED_OUT           = 0x10000004,
-  EMACH_SEND_WILL_NOTIFY         = 0x10000005,
-  EMACH_SEND_NOTIFY_IN_PROGRESS  = 0x10000006,
-  EMACH_SEND_INTERRUPTED         = 0x10000007,
-  EMACH_SEND_MSG_TOO_SMALL       = 0x10000008,
-  EMACH_SEND_INVALID_REPLY       = 0x10000009,
-  EMACH_SEND_INVALID_RIGHT       = 0x1000000a,
-  EMACH_SEND_INVALID_NOTIFY      = 0x1000000b,
-  EMACH_SEND_INVALID_MEMORY      = 0x1000000c,
-  EMACH_SEND_NO_BUFFER           = 0x1000000d,
-  EMACH_SEND_NO_NOTIFY           = 0x1000000e,
-  EMACH_SEND_INVALID_TYPE        = 0x1000000f,
-  EMACH_SEND_INVALID_HEADER      = 0x10000010,
-  EMACH_RCV_IN_PROGRESS          = 0x10004001,
-  EMACH_RCV_INVALID_NAME         = 0x10004002,
-  EMACH_RCV_TIMED_OUT            = 0x10004003,
-  EMACH_RCV_TOO_LARGE            = 0x10004004,
-  EMACH_RCV_INTERRUPTED          = 0x10004005,
-  EMACH_RCV_PORT_CHANGED         = 0x10004006,
-  EMACH_RCV_INVALID_NOTIFY       = 0x10004007,
-  EMACH_RCV_INVALID_DATA         = 0x10004008,
-  EMACH_RCV_PORT_DIED            = 0x10004009,
-  EMACH_RCV_IN_SET               = 0x1000400a,
-  EMACH_RCV_HEADER_ERROR         = 0x1000400b,
-  EMACH_RCV_BODY_ERROR           = 0x1000400c,
-
-/* Errors from <mach/kern_return.h>.  */
-  EKERN_INVALID_ADDRESS          = 1,
-  EKERN_PROTECTION_FAILURE       = 2,
-  EKERN_NO_SPACE                 = 3,
-  EKERN_INVALID_ARGUMENT         = 4,
-  EKERN_FAILURE                  = 5,
-  EKERN_RESOURCE_SHORTAGE        = 6,
-  EKERN_NOT_RECEIVER             = 7,
-  EKERN_NO_ACCESS                = 8,
-  EKERN_MEMORY_FAILURE           = 9,
-  EKERN_MEMORY_ERROR             = 10,
-  EKERN_NOT_IN_SET               = 12,
-  EKERN_NAME_EXISTS              = 13,
-  EKERN_ABORTED                  = 14,
-  EKERN_INVALID_NAME             = 15,
-  EKERN_INVALID_TASK             = 16,
-  EKERN_INVALID_RIGHT            = 17,
-  EKERN_INVALID_VALUE            = 18,
-  EKERN_UREFS_OVERFLOW           = 19,
-  EKERN_INVALID_CAPABILITY       = 20,
-  EKERN_RIGHT_EXISTS             = 21,
-  EKERN_INVALID_HOST             = 22,
-  EKERN_MEMORY_PRESENT           = 23,
-  EKERN_WRITE_PROTECTION_FAILURE = 24,
-  EKERN_TERMINATED               = 26,
-  EKERN_TIMEDOUT                 = 27,
-  EKERN_INTERRUPTED              = 28,
-
-/* Errors from <mach/mig_errors.h>.  */
-  EMIG_TYPE_ERROR                = -300,	/* client type check failure */
-  EMIG_REPLY_MISMATCH            = -301,	/* wrong reply message ID */
-  EMIG_REMOTE_ERROR              = -302,	/* server detected error */
-  EMIG_BAD_ID                    = -303,	/* bad request message ID */
-  EMIG_BAD_ARGUMENTS             = -304,	/* server type check failure */
-  EMIG_NO_REPLY                  = -305,	/* no reply should be sent */
-  EMIG_EXCEPTION                 = -306,	/* server raised exception */
-  EMIG_ARRAY_TOO_LARGE           = -307,	/* array not large enough */
-  EMIG_SERVER_DIED               = -308,	/* server died */
-  EMIG_DESTROY_REQUEST           = -309,	/* destroy request with no reply */
-
-/* Errors from <device/device_types.h>.  */
-  ED_IO_ERROR                    = 2500,	/* hardware IO error */
-  ED_WOULD_BLOCK                 = 2501,	/* would block, but D_NOWAIT set */
-  ED_NO_SUCH_DEVICE              = 2502,	/* no such device */
-  ED_ALREADY_OPEN                = 2503,	/* exclusive-use device already open */
-  ED_DEVICE_DOWN                 = 2504,	/* device has been shut down */
-  ED_INVALID_OPERATION           = 2505,	/* bad operation for device */
-  ED_INVALID_RECNUM              = 2506,	/* invalid record (block) number */
-  ED_INVALID_SIZE                = 2507,	/* invalid IO size */
-  ED_NO_MEMORY                   = 2508,	/* memory allocation failure */
-  ED_READ_ONLY                   = 2509,	/* device cannot be written to */
-
-  /* Because the C standard requires that errno have type 'int',
-     this enumeration must be a signed type.  */
-  __FORCE_ERROR_T_CODES_SIGNED = -1
-};
-
-/* User-visible type of error codes.  It is ok to use 'int' or
-   'kern_return_t' for these, but with 'error_t' the debugger prints
-   symbolic values.  */
-# if !defined __error_t_defined && defined __USE_GNU
-#  define __error_t_defined 1
-typedef enum __error_t_codes error_t;
-# endif
-
-#endif /* not __ASSEMBLER__ */
-
-/* The C standard requires that all of the E-constants be
-   defined as macros.  */
-
-#define EPERM                          0x40000001
-#define ENOENT                         0x40000002
-#define ESRCH                          0x40000003
-#define EINTR                          0x40000004
-#define EIO                            0x40000005
-#define ENXIO                          0x40000006
-#define E2BIG                          0x40000007
-#define ENOEXEC                        0x40000008
-#define EBADF                          0x40000009
-#define ECHILD                         0x4000000a
-#define EDEADLK                        0x4000000b
-#define ENOMEM                         0x4000000c
-#define EACCES                         0x4000000d
-#define EFAULT                         0x4000000e
-#define ENOTBLK                        0x4000000f
-#define EBUSY                          0x40000010
-#define EEXIST                         0x40000011
-#define EXDEV                          0x40000012
-#define ENODEV                         0x40000013
-#define ENOTDIR                        0x40000014
-#define EISDIR                         0x40000015
-#define EINVAL                         0x40000016
-#define EMFILE                         0x40000018
-#define ENFILE                         0x40000017
-#define ENOTTY                         0x40000019
-#define ETXTBSY                        0x4000001a
-#define EFBIG                          0x4000001b
-#define ENOSPC                         0x4000001c
-#define ESPIPE                         0x4000001d
-#define EROFS                          0x4000001e
-#define EMLINK                         0x4000001f
-#define EPIPE                          0x40000020
-#define EDOM                           0x40000021
-#define ERANGE                         0x40000022
-#define EAGAIN                         0x40000023
+/* The Hurd uses Mach error system 0x10, subsystem 0. */
+
+#define EPERM                          0x40000001	/* Operation not permitted */
+#define ENOENT                         0x40000002	/* No such file or directory */
+#define ESRCH                          0x40000003	/* No such process */
+#define EINTR                          0x40000004	/* Interrupted system call */
+#define EIO                            0x40000005	/* Input/output error */
+#define ENXIO                          0x40000006	/* No such device or address */
+#define E2BIG                          0x40000007	/* Argument list too long */
+#define ENOEXEC                        0x40000008	/* Exec format error */
+#define EBADF                          0x40000009	/* Bad file descriptor */
+#define ECHILD                         0x4000000a	/* No child processes */
+#define EDEADLK                        0x4000000b	/* Resource deadlock avoided */
+#define ENOMEM                         0x4000000c	/* Cannot allocate memory */
+#define EACCES                         0x4000000d	/* Permission denied */
+#define EFAULT                         0x4000000e	/* Bad address */
+#define ENOTBLK                        0x4000000f	/* Block device required */
+#define EBUSY                          0x40000010	/* Device or resource busy */
+#define EEXIST                         0x40000011	/* File exists */
+#define EXDEV                          0x40000012	/* Invalid cross-device link */
+#define ENODEV                         0x40000013	/* No such device */
+#define ENOTDIR                        0x40000014	/* Not a directory */
+#define EISDIR                         0x40000015	/* Is a directory */
+#define EINVAL                         0x40000016	/* Invalid argument */
+#define EMFILE                         0x40000018	/* Too many open files */
+#define ENFILE                         0x40000017	/* Too many open files in system */
+#define ENOTTY                         0x40000019	/* Inappropriate ioctl for device */
+#define ETXTBSY                        0x4000001a	/* Text file busy */
+#define EFBIG                          0x4000001b	/* File too large */
+#define ENOSPC                         0x4000001c	/* No space left on device */
+#define ESPIPE                         0x4000001d	/* Illegal seek */
+#define EROFS                          0x4000001e	/* Read-only file system */
+#define EMLINK                         0x4000001f	/* Too many links */
+#define EPIPE                          0x40000020	/* Broken pipe */
+#define EDOM                           0x40000021	/* Numerical argument out of domain */
+#define ERANGE                         0x40000022	/* Numerical result out of range */
+#define EAGAIN                         0x40000023	/* Resource temporarily unavailable */
 #define EWOULDBLOCK                    EAGAIN
-#define EINPROGRESS                    0x40000024
-#define EALREADY                       0x40000025
-#define ENOTSOCK                       0x40000026
-#define EMSGSIZE                       0x40000028
-#define EPROTOTYPE                     0x40000029
-#define ENOPROTOOPT                    0x4000002a
-#define EPROTONOSUPPORT                0x4000002b
-#define ESOCKTNOSUPPORT                0x4000002c
-#define EOPNOTSUPP                     0x4000002d
-#define EPFNOSUPPORT                   0x4000002e
-#define EAFNOSUPPORT                   0x4000002f
-#define EADDRINUSE                     0x40000030
-#define EADDRNOTAVAIL                  0x40000031
-#define ENETDOWN                       0x40000032
-#define ENETUNREACH                    0x40000033
-#define ENETRESET                      0x40000034
-#define ECONNABORTED                   0x40000035
-#define ECONNRESET                     0x40000036
-#define ENOBUFS                        0x40000037
-#define EISCONN                        0x40000038
-#define ENOTCONN                       0x40000039
-#define EDESTADDRREQ                   0x40000027
-#define ESHUTDOWN                      0x4000003a
-#define ETOOMANYREFS                   0x4000003b
-#define ETIMEDOUT                      0x4000003c
-#define ECONNREFUSED                   0x4000003d
-#define ELOOP                          0x4000003e
-#define ENAMETOOLONG                   0x4000003f
-#define EHOSTDOWN                      0x40000040
-#define EHOSTUNREACH                   0x40000041
-#define ENOTEMPTY                      0x40000042
-#define EPROCLIM                       0x40000043
-#define EUSERS                         0x40000044
-#define EDQUOT                         0x40000045
-#define ESTALE                         0x40000046
-#define EREMOTE                        0x40000047
-#define EBADRPC                        0x40000048
-#define ERPCMISMATCH                   0x40000049
-#define EPROGUNAVAIL                   0x4000004a
-#define EPROGMISMATCH                  0x4000004b
-#define EPROCUNAVAIL                   0x4000004c
-#define ENOLCK                         0x4000004d
-#define EFTYPE                         0x4000004f
-#define EAUTH                          0x40000050
-#define ENEEDAUTH                      0x40000051
-#define ENOSYS                         0x4000004e
-#define ENOTSUP                        0x40000076
-#define EILSEQ                         0x4000006a
-#define EBACKGROUND                    0x40000064
-#define EDIED                          0x40000065
-#define ED                             0x40000066
-#define EGREGIOUS                      0x40000067
-#define EIEIO                          0x40000068
-#define EGRATUITOUS                    0x40000069
-#define EBADMSG                        0x4000006b
-#define EIDRM                          0x4000006c
-#define EMULTIHOP                      0x4000006d
-#define ENODATA                        0x4000006e
-#define ENOLINK                        0x4000006f
-#define ENOMSG                         0x40000070
-#define ENOSR                          0x40000071
-#define ENOSTR                         0x40000072
-#define EOVERFLOW                      0x40000073
-#define EPROTO                         0x40000074
-#define ETIME                          0x40000075
-#define ECANCELED                      0x40000077
+#define EINPROGRESS                    0x40000024	/* Operation now in progress */
+#define EALREADY                       0x40000025	/* Operation already in progress */
+#define ENOTSOCK                       0x40000026	/* Socket operation on non-socket */
+#define EMSGSIZE                       0x40000028	/* Message too long */
+#define EPROTOTYPE                     0x40000029	/* Protocol wrong type for socket */
+#define ENOPROTOOPT                    0x4000002a	/* Protocol not available */
+#define EPROTONOSUPPORT                0x4000002b	/* Protocol not supported */
+#define ESOCKTNOSUPPORT                0x4000002c	/* Socket type not supported */
+#define EOPNOTSUPP                     0x4000002d	/* Operation not supported */
+#define EPFNOSUPPORT                   0x4000002e	/* Protocol family not supported */
+#define EAFNOSUPPORT                   0x4000002f	/* Address family not supported by protocol */
+#define EADDRINUSE                     0x40000030	/* Address already in use */
+#define EADDRNOTAVAIL                  0x40000031	/* Cannot assign requested address */
+#define ENETDOWN                       0x40000032	/* Network is down */
+#define ENETUNREACH                    0x40000033	/* Network is unreachable */
+#define ENETRESET                      0x40000034	/* Network dropped connection on reset */
+#define ECONNABORTED                   0x40000035	/* Software caused connection abort */
+#define ECONNRESET                     0x40000036	/* Connection reset by peer */
+#define ENOBUFS                        0x40000037	/* No buffer space available */
+#define EISCONN                        0x40000038	/* Transport endpoint is already connected */
+#define ENOTCONN                       0x40000039	/* Transport endpoint is not connected */
+#define EDESTADDRREQ                   0x40000027	/* Destination address required */
+#define ESHUTDOWN                      0x4000003a	/* Cannot send after transport endpoint shutdown */
+#define ETOOMANYREFS                   0x4000003b	/* Too many references: cannot splice */
+#define ETIMEDOUT                      0x4000003c	/* Connection timed out */
+#define ECONNREFUSED                   0x4000003d	/* Connection refused */
+#define ELOOP                          0x4000003e	/* Too many levels of symbolic links */
+#define ENAMETOOLONG                   0x4000003f	/* File name too long */
+#define EHOSTDOWN                      0x40000040	/* Host is down */
+#define EHOSTUNREACH                   0x40000041	/* No route to host */
+#define ENOTEMPTY                      0x40000042	/* Directory not empty */
+#define EPROCLIM                       0x40000043	/* Too many processes */
+#define EUSERS                         0x40000044	/* Too many users */
+#define EDQUOT                         0x40000045	/* Disk quota exceeded */
+#define ESTALE                         0x40000046	/* Stale file handle */
+#define EREMOTE                        0x40000047	/* Object is remote */
+#define EBADRPC                        0x40000048	/* RPC struct is bad */
+#define ERPCMISMATCH                   0x40000049	/* RPC version wrong */
+#define EPROGUNAVAIL                   0x4000004a	/* RPC program not available */
+#define EPROGMISMATCH                  0x4000004b	/* RPC program version wrong */
+#define EPROCUNAVAIL                   0x4000004c	/* RPC bad procedure for program */
+#define ENOLCK                         0x4000004d	/* No locks available */
+#define EFTYPE                         0x4000004f	/* Inappropriate file type or format */
+#define EAUTH                          0x40000050	/* Authentication error */
+#define ENEEDAUTH                      0x40000051	/* Need authenticator */
+#define ENOSYS                         0x4000004e	/* Function not implemented */
+#define ENOTSUP                        0x40000076	/* Not supported */
+#define EILSEQ                         0x4000006a	/* Invalid or incomplete multibyte or wide character */
+#define EBACKGROUND                    0x40000064	/* Inappropriate operation for background process */
+#define EDIED                          0x40000065	/* Translator died */
+#define ED                             0x40000066	/* ? */
+#define EGREGIOUS                      0x40000067	/* You really blew it this time */
+#define EIEIO                          0x40000068	/* Computer bought the farm */
+#define EGRATUITOUS                    0x40000069	/* Gratuitous error */
+#define EBADMSG                        0x4000006b	/* Bad message */
+#define EIDRM                          0x4000006c	/* Identifier removed */
+#define EMULTIHOP                      0x4000006d	/* Multihop attempted */
+#define ENODATA                        0x4000006e	/* No data available */
+#define ENOLINK                        0x4000006f	/* Link has been severed */
+#define ENOMSG                         0x40000070	/* No message of desired type */
+#define ENOSR                          0x40000071	/* Out of streams resources */
+#define ENOSTR                         0x40000072	/* Device not a stream */
+#define EOVERFLOW                      0x40000073	/* Value too large for defined data type */
+#define EPROTO                         0x40000074	/* Protocol error */
+#define ETIME                          0x40000075	/* Timer expired */
+#define ECANCELED                      0x40000077	/* Operation canceled */
 
 /* Errors from <mach/message.h>.  */
 #define EMACH_SEND_IN_PROGRESS         0x10000001
@@ -390,28 +177,28 @@ typedef enum __error_t_codes error_t;
 #define EKERN_INTERRUPTED              28
 
 /* Errors from <mach/mig_errors.h>.  */
-#define EMIG_TYPE_ERROR                -300
-#define EMIG_REPLY_MISMATCH            -301
-#define EMIG_REMOTE_ERROR              -302
-#define EMIG_BAD_ID                    -303
-#define EMIG_BAD_ARGUMENTS             -304
-#define EMIG_NO_REPLY                  -305
-#define EMIG_EXCEPTION                 -306
-#define EMIG_ARRAY_TOO_LARGE           -307
-#define EMIG_SERVER_DIED               -308
-#define EMIG_DESTROY_REQUEST           -309
+#define EMIG_TYPE_ERROR                -300	/* client type check failure */
+#define EMIG_REPLY_MISMATCH            -301	/* wrong reply message ID */
+#define EMIG_REMOTE_ERROR              -302	/* server detected error */
+#define EMIG_BAD_ID                    -303	/* bad request message ID */
+#define EMIG_BAD_ARGUMENTS             -304	/* server type check failure */
+#define EMIG_NO_REPLY                  -305	/* no reply should be sent */
+#define EMIG_EXCEPTION                 -306	/* server raised exception */
+#define EMIG_ARRAY_TOO_LARGE           -307	/* array not large enough */
+#define EMIG_SERVER_DIED               -308	/* server died */
+#define EMIG_DESTROY_REQUEST           -309	/* destroy request with no reply */
 
 /* Errors from <device/device_types.h>.  */
-#define ED_IO_ERROR                    2500
-#define ED_WOULD_BLOCK                 2501
-#define ED_NO_SUCH_DEVICE              2502
-#define ED_ALREADY_OPEN                2503
-#define ED_DEVICE_DOWN                 2504
-#define ED_INVALID_OPERATION           2505
-#define ED_INVALID_RECNUM              2506
-#define ED_INVALID_SIZE                2507
-#define ED_NO_MEMORY                   2508
-#define ED_READ_ONLY                   2509
+#define ED_IO_ERROR                    2500	/* hardware IO error */
+#define ED_WOULD_BLOCK                 2501	/* would block, but D_NOWAIT set */
+#define ED_NO_SUCH_DEVICE              2502	/* no such device */
+#define ED_ALREADY_OPEN                2503	/* exclusive-use device already open */
+#define ED_DEVICE_DOWN                 2504	/* device has been shut down */
+#define ED_INVALID_OPERATION           2505	/* bad operation for device */
+#define ED_INVALID_RECNUM              2506	/* invalid record (block) number */
+#define ED_INVALID_SIZE                2507	/* invalid IO size */
+#define ED_NO_MEMORY                   2508	/* memory allocation failure */
+#define ED_READ_ONLY                   2509	/* device cannot be written to */
 
 #define _HURD_ERRNOS 120
 
diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
index 4f274b4..94be85e 100644
--- a/sysdeps/mach/hurd/dl-sysdep.c
+++ b/sysdeps/mach/hurd/dl-sysdep.c
@@ -23,6 +23,7 @@
 #include <hurd.h>
 #include <link.h>
 #include <unistd.h>
+#include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <sys/mman.h>
@@ -69,7 +70,7 @@ struct hurd_startup_data *_dl_hurd_data;
 
 /* This is used only within ld.so, via dl-minimal.c's __errno_location.  */
 #undef errno
-int errno attribute_hidden;
+__error_t errno attribute_hidden;
 
 /* Defining these variables here avoids the inclusion of hurdsig.c.  */
 unsigned long int __hurd_sigthread_stack_base;
diff --git a/sysdeps/mach/hurd/errno-loc.c b/sysdeps/mach/hurd/errno-loc.c
index 039c9fc..0a9eae1 100644
--- a/sysdeps/mach/hurd/errno-loc.c
+++ b/sysdeps/mach/hurd/errno-loc.c
@@ -19,7 +19,7 @@
 #include <errno.h>
 #include <hurd/threadvar.h>
 
-int *
+__error_t *
 __errno_location (void)
 {
   return (int *) __hurd_threadvar_location (_HURD_THREADVAR_ERRNO);
diff --git a/sysdeps/mach/hurd/errno.c b/sysdeps/mach/hurd/errno.c
deleted file mode 100644
index a29091b..0000000
--- a/sysdeps/mach/hurd/errno.c
+++ /dev/null
@@ -1 +0,0 @@
-/* No definition of `errno' variable on the Hurd.  */
diff --git a/sysdeps/mach/hurd/errnos.awk b/sysdeps/mach/hurd/errnos.awk
index 1fdca40..c5d33b5 100644
--- a/sysdeps/mach/hurd/errnos.awk
+++ b/sysdeps/mach/hurd/errnos.awk
@@ -15,31 +15,18 @@
 # License along with the GNU C Library; if not, see
 # <http://www.gnu.org/licenses/>.
 
-# errno.texinfo contains lines like:
-# @errno{ENOSYS, 123, Function not implemented}
+# Generate bits/errno.h from errnos.texi and a number of Mach headers.
+# This script must be kept in sync with stdlib/make-errno-constants.awk
+# and hurd-add-errno-constants.awk.
 
 BEGIN {
-    print "/* This file generated by errnos.awk from";
-    for (i = 1; i < ARGC; i++)
-      {
-	arg = ARGV[i];
-	sub(/.*(manual|include)\//, "", arg)
-	print "     " arg;
-      }
-    print "   Do not edit this file; edit errnos.awk and regenerate it.  */";
-    print "";
-    print "#ifndef _BITS_ERRNO_H";
-    print "#define _BITS_ERRNO_H 1";
-    print "";
-    print "#if !defined _ERRNO_H";
-    print "# error \"Never include <bits/errno.h> directly; use <errno.h> instead.\"";
-    print "#endif";
-
-    maxerrno = 0;
-    maxerrlen = 0;
-    in_mach_errors = "";
-    seq = 0;
-  }
+  maxerrno = 0;
+  maxerrlen = 0;
+  in_mach_errors = "";
+  in_mig_errors = 0;
+  in_device_errors = 0;
+  seq = 0;
+}
 
 /^@errno\{/ \
   {
@@ -147,73 +134,37 @@ in_device_errors && $1 == "#endif" \
     in_device_errors = 0;
   }
 
-function print_errno_enum(maxseq)
-{
-  print "";
-  print "#ifndef __ASSEMBLER__";
-  print "";
-  print "enum __error_t_codes";
-  print "{";
-  print "  /* The value zero always means success and it is perfectly fine";
-  print "     for code to use 0 explicitly (or implicitly, e.g. via Boolean";
-  print "     coercion.)  Having an enum entry for zero both makes the";
-  print "     debugger print the name for error_t-typed zero values, and";
-  print "     prevents the compiler from issuing warnings about 'case 0:'";
-  print "     in a switch on an error_t-typed value.  */";
-  printf("  %-*s = 0,\n", maxerrlen, "ESUCCESS");
-
-  print "";
-  print "  /* The Hurd uses Mach error system 0x10, subsystem 0. */";
-  for (i = 0; i < maxseq; i++)
+END {
+  print "/* This file generated by errnos.awk from";
+  for (i = 1; i < ARGC; i++)
     {
-      if (i in annot)
-	print annot[i];
-      else if (i in etexts && etexts[i] != "")
-	printf("  %-*s = %s,\t/* %s */\n",
-	       maxerrlen, econsts[i], errnos[i], etexts[i]);
-      else if (errnos[i] != "EAGAIN")
-	printf("  %-*s = %s,\n", maxerrlen, econsts[i], errnos[i]);
+	arg = ARGV[i];
+	sub(/.*(manual|include)\//, "", arg)
+	print "     " arg;
     }
-
-  print "";
-  print "  /* Because the C standard requires that errno have type 'int',"
-  print "     this enumeration must be a signed type.  */";
-  print "  __FORCE_ERROR_T_CODES_SIGNED = -1";
-  print "};";
+  print "   Do not edit this file; edit errnos.awk and regenerate it.  */";
   print "";
-  print "/* User-visible type of error codes.  It is ok to use 'int' or";
-  print "   'kern_return_t' for these, but with 'error_t' the debugger prints";
-  print "   symbolic values.  */";
-  print "# if !defined __error_t_defined && defined __USE_GNU";
-  print "#  define __error_t_defined 1";
-  print "typedef enum __error_t_codes error_t;"
-  print "# endif";
+  print "#ifndef _BITS_ERRNO_H";
+  print "#define _BITS_ERRNO_H 1";
   print "";
-  print "#endif /* not __ASSEMBLER__ */";
-}
-
-function print_errno_defines(maxseq)
-{
+  print "#if !defined _ERRNO_H";
+  print "# error \"Never include <bits/errno.h> directly; use <errno.h> instead.\"";
+  print "#endif";
   print "";
-  print "/* The C standard requires that all of the E-constants be"
-  print "   defined as macros.  */"
+  print "/* The Hurd uses Mach error system 0x10, subsystem 0. */";
   print "";
-  for (i = 0; i < maxseq; i++)
+  for (i = 0; i < seq; i++)
     {
       if (i in annot)
 	print annot[i];
+      else if (i in etexts && etexts[i] != "")
+	printf("#define %-*s %s\t/* %s */\n",
+	       maxerrlen, econsts[i], errnos[i], etexts[i]);
       else
 	printf("#define %-*s %s\n", maxerrlen, econsts[i], errnos[i]);
     }
   print "";
   printf("#define _HURD_ERRNOS %d\n", maxerrno+1);
+  print "";
+  print "#endif /* bits/errno.h.  */";
 }
-
-END \
-  {
-    print_errno_enum(seq);
-    print_errno_defines(seq);
-
-    print "";
-    print "#endif /* bits/errno.h.  */";
-  }

http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=6e5e73539b3fc122df96d653fab3c357a08071a4

commit 6e5e73539b3fc122df96d653fab3c357a08071a4
Author: Zack Weinberg <zackw@panix.com>
Date:   Thu Jun 22 17:53:37 2017 -0400

    Improve testing of GDB pretty-printers.
    
    The C programs used to test GDB pretty-printers were being compiled
    with -DMODULE_NAME=libc (!) which causes many problems, such as
    failure to link if they refer to errno.  Now they are compiled with
    -DMODULE_NAME=testsuite instead.
    
    test_printers_common.py was testing for expected output in a clumsy
    way which meant the pexpect timeout had to expire before it could
    report a failure, even if the regexp was never going to match.  This
    slows down debugging a test quite a bit.  Rewrote that logic so it
    doesn't do that anymore.  Note that as a side effect, test() fails the
    test by calling exit() rather than throwing an exception -- that could
    change if people think it's a bad idea.
    
    Add an 'unsupported_pattern' argument to test(); if the normal
    'pattern' fails to match, but an 'unsupported_pattern' was supplied
    and it matches, then the test fails as unsupported, not as a normal
    failure.  This feature is used in part 2.
    
    Tighten up the code to honor TIMEOUTFACTOR, and add another
    environment variable TEST_PRINTERS_LOG; if this is set to a pathname,
    all of the dialogue with the gdb subprocess will be logged to that
    file.
    
    	* Rules: Set MODULE_NAME=testsuite for everything in tests-printers.
    	* scripts/test_printers_common.py (TIMEOUTFACTOR): Tighten up handling.
    	(TEST_PRINTERS_LOG): New env variable; if set, pexpect will log all
    	dialogue with the gdb subprocess to the file it names.
    	(send_command): New function broken out of test.
    	(test): Add 'unsupported_pattern' argument and improve
    	handling of 'pattern' argument; match failures no longer have to
    	wait for the timeout.

diff --git a/Rules b/Rules
index 168cf50..85b77a0 100644
--- a/Rules
+++ b/Rules
@@ -265,6 +265,10 @@ endif	# tests
 ifdef PYTHON
 ifneq "$(strip $(tests-printers))" ""
 
+cpp-srcs-left := $(tests-printers)
+lib := testsuite
+include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
+
 # Static pattern rule for building the test programs for the pretty printers.
 $(tests-printers-programs): %: %.o $(tests-printers-libs) \
   $(sort $(filter $(common-objpfx)lib%,$(link-libc-static-tests))) \
diff --git a/scripts/test_printers_common.py b/scripts/test_printers_common.py
index fe88f36..aabb9da 100644
--- a/scripts/test_printers_common.py
+++ b/scripts/test_printers_common.py
@@ -54,11 +54,7 @@ if not pexpect.which(gdb_bin):
     print('gdb 7.8 or newer must be installed to test the pretty printers.')
     exit(UNSUPPORTED)
 
-timeout = 5
-TIMEOUTFACTOR = os.environ.get('TIMEOUTFACTOR')
-
-if TIMEOUTFACTOR:
-    timeout = int(TIMEOUTFACTOR)
+timeout = int(os.environ.get('TIMEOUTFACTOR', '5'))
 
 try:
     # Check the gdb version.
@@ -93,15 +89,39 @@ try:
     # If everything's ok, spawn the gdb process we'll use for testing.
     gdb = pexpect.spawn(gdb_invocation, echo=False, timeout=timeout,
                         encoding=encoding)
-    gdb_prompt = u'\(gdb\)'
+    logfile = os.environ.get("TEST_PRINTERS_LOG")
+    if logfile is not None:
+        gdb.logfile = open(logfile, "wt")
+
+    gdb_prompt = u'(?:\A|\r\n)\(gdb\) '
     gdb.expect(gdb_prompt)
 
 except pexpect.ExceptionPexpect as exception:
     print('Error: {0}'.format(exception))
     exit(FAIL)
 
-def test(command, pattern=None):
-    """Sends 'command' to gdb and expects the given 'pattern'.
+def send_command(command):
+    """Sends 'command' to gdb, and returns all output up to but not
+    including the next gdb prompt.  If a gdb prompt is not detected
+    in a timely fashion, raises pexpect.TIMEOUT.
+
+    Args:
+        command (string): The command we'll send to gdb.
+    """
+
+    gdb.sendline(command)
+
+    # PExpect does a non-greedy match for '+' and '*', since it can't
+    # look ahead on the gdb output stream.  Therefore, we must include
+    # the gdb prompt in the match to ensure that all of the output of
+    # the command is captured.
+    gdb.expect(u'(.*?){}'.format(gdb_prompt))
+    return gdb.match.group(1)
+
+
+def test(command, pattern=None, unsupported_pattern=None):
+    """Sends 'command' to gdb and expects the given 'pattern'.  If
+       the match fails, the test fails.
 
     If 'pattern' is None, simply consumes everything up to and including
     the gdb prompt.
@@ -109,43 +129,31 @@ def test(command, pattern=None):
     Args:
         command (string): The command we'll send to gdb.
         pattern (raw string): A pattern the gdb output should match.
+        unsupported_pattern (raw string): If the gdb output fails to
+            match 'pattern', but it _does_ match this, then the test
+            is marked unsupported rather than failing outright.
 
     Returns:
         string: The string that matched 'pattern', or an empty string if
             'pattern' was None.
     """
-
-    match = ''
-
-    gdb.sendline(command)
-
-    if pattern:
-        # PExpect does a non-greedy match for '+' and '*'.  Since it can't look
-        # ahead on the gdb output stream, if 'pattern' ends with a '+' or a '*'
-        # we may end up matching only part of the required output.
-        # To avoid this, we'll consume 'pattern' and anything that follows it
-        # up to and including the gdb prompt, then extract 'pattern' later.
-        index = gdb.expect([u'{0}.+{1}'.format(pattern, gdb_prompt),
-                            pexpect.TIMEOUT])
-
-        if index == 0:
-            # gdb.after now contains the whole match.  Extract the text that
-            # matches 'pattern'.
-            match = re.match(pattern, gdb.after, re.DOTALL).group()
-        elif index == 1:
-            # We got a timeout exception.  Print information on what caused it
-            # and bail out.
-            error = ('Response does not match the expected pattern.\n'
-                     'Command: {0}\n'
-                     'Expected pattern: {1}\n'
-                     'Response: {2}'.format(command, pattern, gdb.before))
-
-            raise pexpect.TIMEOUT(error)
-    else:
-        # Consume just the the gdb prompt.
-        gdb.expect(gdb_prompt)
-
-    return match
+    output = send_command(command)
+    if pattern is None:
+        return None
+
+    match = re.search(pattern, output, re.DOTALL)
+    if not match:
+        if (unsupported_pattern is not None
+            and re.search(unsupported_pattern, output, re.DOTALL)):
+            exit(UNSUPPORTED)
+        else:
+            print('Response does not match the expected pattern.\n'
+                  'Command: {0}\n'
+                  'Expected pattern: {1}\n'
+                  'Response: {2}'.format(command, pattern, output))
+            exit(FAIL)
+
+    return match.group(0)
 
 def init_test(test_bin, printer_files, printer_names):
     """Loads the test binary file and the required pretty printers to gdb.

-----------------------------------------------------------------------


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]