about summary refs log tree commit diff
path: root/stdio-common
diff options
context:
space:
mode:
Diffstat (limited to 'stdio-common')
-rw-r--r--stdio-common/Makefile11
-rw-r--r--stdio-common/errlist-compat.c1
-rw-r--r--stdio-common/errlist.c30
-rwxr-xr-xstdio-common/tst-errno-manual.py73
4 files changed, 101 insertions, 14 deletions
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
index 1333203046..73bf0da296 100644
--- a/stdio-common/Makefile
+++ b/stdio-common/Makefile
@@ -85,6 +85,8 @@ generated += tst-printf-bz18872.c tst-printf-bz18872.mtrace \
 	     tst-printf-bz25691.mtrace tst-printf-bz25691-mem.out
 endif
 
+tests-special += $(objpfx)tst-errno-manual.out
+
 include ../Rules
 
 ifeq ($(run-built-tests),yes)
@@ -129,6 +131,15 @@ $(objpfx)tst-%-mem.out: $(objpfx)tst-%.out
 	$(common-objpfx)malloc/mtrace $(objpfx)tst-$*.mtrace > $@; \
 	$(evaluate-test)
 
+errlist-h = $(firstword $(wildcard $(addsuffix /errlist.h,$(sysdirs) .)))
+
+$(objpfx)tst-errno-manual.out: tst-errno-manual.py \
+			       $(errlist-h) \
+			       $(..)manual/errno.texi
+	$(PYTHON) tst-errno-manual.py -m $(..)manual/errno.texi \
+				      -e $(errlist-h) > $@; \
+	$(evaluate-test)
+
 CFLAGS-vfprintf.c += -Wno-uninitialized
 CFLAGS-vfwprintf.c += -Wno-uninitialized
 
diff --git a/stdio-common/errlist-compat.c b/stdio-common/errlist-compat.c
new file mode 100644
index 0000000000..6e25b021ab
--- /dev/null
+++ b/stdio-common/errlist-compat.c
@@ -0,0 +1 @@
+/* Empty.  */
diff --git a/stdio-common/errlist.c b/stdio-common/errlist.c
index 91fa789be0..df52356066 100644
--- a/stdio-common/errlist.c
+++ b/stdio-common/errlist.c
@@ -15,22 +15,24 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#include <stdio.h>
+#include <errno.h>
+#include <libintl.h>
 #include <array_length.h>
-#include <stddef.h>
 
-const char *const _sys_errlist[] =
+const char *const _sys_errlist_internal[] =
   {
-    "Error 0",			/* 0 */
-    "Argument out of function's domain", /* 1 = EDOM */
-    "Result out of range",	/* 2 = ERANGE */
-    "Operation not implemented", /* 3 = ENOSYS */
-    "Invalid argument",		/* 4 = EINVAL */
-    "Illegal seek",		/* 5 = ESPIPE */
-    "Bad file descriptor",	/* 6 = EBADF */
-    "Cannot allocate memory",	/* 7 = ENOMEM */
-    "Permission denied",	/* 8 = EACCES */
-    "Too many open files in system", /* 9 = ENFILE */
-    "Too many open files",	/* 10 = EMFILE */
+#define _S(n, str)         [n] = str,
+#include <errlist.h>
+#undef _S
   };
 
-const int _sys_nerr = array_length (_sys_errlist);
+const char *
+__get_errlist (int errnum)
+{
+  if (errnum >= 0 && errnum < array_length (_sys_errlist_internal))
+    return _sys_errlist_internal[errnum];
+  return NULL;
+}
+
+#include <errlist-compat.c>
diff --git a/stdio-common/tst-errno-manual.py b/stdio-common/tst-errno-manual.py
new file mode 100755
index 0000000000..618120f4f0
--- /dev/null
+++ b/stdio-common/tst-errno-manual.py
@@ -0,0 +1,73 @@
+#!/usr/bin/python3
+# Check is all errno definitions at errlist.h documented in the manual.
+# Copyright (C) 2020 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
+# <https://www.gnu.org/licenses/>.
+
+import argparse
+import sys
+import re
+
+RE_MANUAL = re.compile(
+    r'(?:^@errno){(\w+)')
+
+RE_ERRLIST = re.compile(
+    r'\(E[a-zA-Z0-9]+\)')
+
+PASS=0
+FAIL=1
+
+# Each manual entry is in the form:
+#
+#  errno{EAGAIN, 35, Resource temporarily unavailable}
+def parse_manual(f):
+    errlist = [RE_MANUAL.findall(s) for s in f]
+    return map(lambda x : x[0], filter(None, errlist))
+
+# Each errlist entry is in the form:
+#
+#  _S(ERR_MAP(EAGAIN), N_("Resource temporarily unavailable"))
+def parse_errlist(f):
+    errlist = [RE_ERRLIST.findall(s) for s in f]
+    # Each element is '[]' or '['(EAGAIN)']'
+    return map(lambda s : s[0][s[0].find('(')+1:s[0].find(')')],
+               filter(None, errlist))
+
+def check_errno_definitions(manual_fname, errlist_fname):
+    with open(manual_fname, 'r') as mfile, open(errlist_fname, 'r') as efile:
+        merr = parse_manual(mfile)
+        eerr = parse_errlist(efile)
+        diff = set(eerr).difference(merr)
+        if not diff:
+            sys.exit(PASS)
+        else:
+            print("Failure: the following value(s) are not in manual:",
+                  ", ".join(str(e) for e in diff))
+            sys.exit(FAIL)
+
+def main():
+    parser = argparse.ArgumentParser(description='Generate errlist.h')
+    parser.add_argument('-m', dest='manual', metavar='FILE',
+                        help='manual errno texi file')
+    parser.add_argument('-e', dest='errlist', metavar='FILE',
+                        help='errlist with errno definitions')
+    args = parser.parse_args()
+
+    check_errno_definitions(args.manual, args.errlist)
+
+
+if __name__ == '__main__':
+    main()