error.c: better strerror for size
authorAlan Cox <alan@linux.intel.com>
Wed, 20 May 2015 13:10:37 +0000 (14:10 +0100)
committerAlan Cox <alan@linux.intel.com>
Wed, 20 May 2015 13:10:37 +0000 (14:10 +0100)
Remove all the funky parsing and use a binary error list for strerror. That
saves us about 500 bytes in many applications.

Library/libs/error.c

index 3af05e2..c9723e9 100644 (file)
@@ -1,54 +1,52 @@
 /* Copyright (C) 1996 Robert de Bath <robert@debath.thenet.co.uk>\r
  * This file is part of the Linux-8086 C library and is distributed\r
  * under the GNU Library General Public License.\r
+ *\r
+ * Rewritten by Alan Cox to use a binary file format and save a lot of space\r
  */  \r
 #include <unistd.h>\r
 #include <string.h>\r
 #include <stdlib.h>\r
 #include <paths.h>\r
 #include <errno.h>\r
+#include <fcntl.h>\r
 \r
-char **__sys_errlist = 0;
-int __sys_nerr = 0;
+static uint8_t *__sys_errlist;
+static uint16_t *__sys_errptr;
+static int __sys_nerr;
+static char retbuf[80];
 \r
+static void _load_errlist(void)\r
+{\r
+       struct stat st;\r
+       int fd = open(_PATH_LIBERR, O_RDONLY);\r
+       if (fd < 0)\r
+               return;\r
+       if (fstat(fd, &st) < 0 || !S_ISREG(st.st_mode))\r
+               goto bad;\r
+       __sys_errlist = sbrk((st.st_size + 3)&~3);\r
+       if (__sys_errlist == (void *) -1)\r
+               goto bad;\r
+       if (read(fd,__sys_errlist, st.st_size) == st.st_size) {\r
+               __sys_nerr = *__sys_errlist;\r
+               __sys_errptr = (uint16_t *)__sys_errlist + 2;\r
+               close(fd);\r
+               return;\r
+       }\r
+bad:\r
+       close(fd);\r
+       __sys_errlist = NULL;\r
+       return;\r
+}\r
+       \r
 char *strerror(int err) \r
-{
-       static char retbuf[80];
-       char *p, inbuf[128];
-       int cc, fd;
-       uint i, bufoff = 0;
-       if (__sys_nerr) {       /* sys_errlist preloaded */
-               if (err < 0 || err >= __sys_nerr)
-                       goto UErr;
-               return __sys_errlist[err];
-       }
-       if (err <= 0)
-               goto UErr;      /* NB the <= allows comments in the file */
-       if ((fd = open(_PATH_LIBERR, 0)) < 0)
-               goto UErr;
-       while ((cc = read(fd, inbuf, sizeof(inbuf))) > 0) {
-               i = 0;
-               while (i < cc) {
-                       if (inbuf[i] == '\n') {
-                               retbuf[bufoff] = '\0';
-                               if (err == atoi(retbuf)) {
-                                       if ((p = strchr(retbuf,' ')) == NULL) {
-                                               close(fd);
-                                               goto UErr;
-                                       }
-                                       while (*p == ' ')
-                                               p++;
-                                       close(fd);
-                                       return p;
-                               }
-                               bufoff = 0;
-                       }
-                       else if (bufoff < sizeof(retbuf) - 1)
-                               retbuf[bufoff++] = inbuf[i];
-                       ++i;
-               }
-       }
-UErr:  strcpy(retbuf, "Unknown error ");\r
-       strncat(retbuf, _itoa(err), 10);
+{\r
+\r
+       if (!__sys_errlist)\r
+               _load_errlist();\r
+       if (__sys_errlist && err >= 0 && err < __sys_nerr)\r
+               return __sys_errlist[__sys_errptr[err]];\r
+       strcpy(retbuf, "Unknown error ");\r
+       strcpy(retbuf + 14, _itoa(err));
        return retbuf;
 }