This time for terminfo.  These are the same basic changes I've made
to getcap.c but applied to getinfo.c.

Before:
$ /usr/bin/time cap_mkdb -i -f obj/terminfo obj/terminfo.src
        6.57 real         5.51 user         0.93 sys

After:
$ /usr/bin/time cap_mkdb -i -f obj/terminfo obj/terminfo.src
        4.03 real         3.62 user         0.24 sys

 - todd

Index: usr.bin/cap_mkdb/getinfo.c
===================================================================
RCS file: /home/cvs/openbsd/src/usr.bin/cap_mkdb/getinfo.c,v
retrieving revision 1.17
diff -u -r1.17 getinfo.c
--- usr.bin/cap_mkdb/getinfo.c  4 Jul 2011 21:34:54 -0000       1.17
+++ usr.bin/cap_mkdb/getinfo.c  9 Jul 2011 20:51:11 -0000
@@ -50,7 +50,7 @@
 #define TCERR  (char)1
 #define        SHADOW  (char)2
 
-static int      getent(char **, u_int *, char **, int, char *, int);
+static int      getent(char **, u_int *, char **, FILE *, char *, int);
 static char    *igetcap(char *, char *, int);
 static int      igetmatch(char *, char *);
 static int      igetclose(void);
@@ -111,8 +111,8 @@
 }
 
 /*
- * Getent implements the functions of igetent.  If fd is non-negative,
- * *db_array has already been opened and fd is the open file descriptor.  We
+ * Getent implements the functions of igetent.  If fp is non-NULL,
+ * *db_array has already been opened and fp is the open file descriptor.  We
  * do this to save time and avoid using up file descriptors for use=
  * recursions.
  *
@@ -129,7 +129,7 @@
  *       MAX_RECURSION.
  */
 static int
-getent(char **cap, u_int *len, char **db_array, int fd, char *name, int depth)
+getent(char **cap, u_int *len, char **db_array, FILE *fp, char *name, int 
depth)
 {
        char *r_end, *rp, **db_p;
        int myfd, eof, foundit;
@@ -143,6 +143,21 @@
        if (depth > MAX_RECURSION)
                return (-3);
 
+        /*
+         * If no name we better have a record in cap
+         */
+        if (depth == 0 && name == NULL) {
+                if ((record = malloc(*len + 1 + BFRAG)) == NULL)
+                        return (-2);
+                memcpy(record, *cap, *len);
+                myfd = 0;
+                db_p = db_array;
+                rp = record + *len + 1;
+                r_end = rp + BFRAG;
+               *rp = '\0';
+                goto exp_use;
+        }
+
        /*
         * Allocate first chunk of memory.
         */
@@ -154,10 +169,10 @@
        foundit = 0;
        rp = NULL;
        myfd = -1;
+
        /*
         * Loop through database array until finding the record.
         */
-
        for (db_p = db_array; *db_p != NULL; db_p++) {
                eof = 0;
 
@@ -165,12 +180,12 @@
                 * Open database if not already open.
                 */
 
-               if (fd >= 0) {
-                       (void)lseek(fd, (off_t)0, SEEK_SET);
+               if (fp != NULL) {
+                       (void)fseek(fp, 0L, SEEK_SET);
                        myfd = 0;
                } else {
-                       fd = open(*db_p, O_RDONLY, 0);
-                       if (fd < 0) {
+                       fp = fopen(*db_p, "r");
+                       if (fp == NULL) {
                                /* No error on unfound file. */
                                continue;
                        }
@@ -197,26 +212,24 @@
                for (;;) {
 
                        /*
-                        * Read in a line implementing (\, newline)
-                        * line continuation.
+                        * Read in a record implementing line continuation.
                         */
                        rp = record;
                        for (;;) {
                                if (bp >= b_end) {
-                                       int n;
+                                       size_t n;
 
-                                       n = read(fd, buf, sizeof(buf));
-                                       if (n <= 0) {
+                                       n = fread(buf, 1, sizeof(buf), fp);
+                                       if (n == 0) {
+                                               eof = feof(fp);
                                                if (myfd)
-                                                       (void)close(fd);
-                                               if (n < 0) {
-                                                       free(record);
-                                                       return (-2);
-                                               } else {
-                                                       fd = -1;
-                                                       eof = 1;
+                                                       (void)fclose(fp);
+                                               if (eof) {
+                                                       fp = NULL;
                                                        break;
                                                }
+                                               free(record);
+                                               return (-2);
                                        }
                                        b_end = buf+n;
                                        bp = buf;
@@ -225,20 +238,19 @@
                                c = *bp++;
                                if (c == '\n') {
                                        if (bp >= b_end) {
-                                               int n;
+                                               size_t n;
 
-                                               n = read(fd, buf, sizeof(buf));
-                                               if (n <= 0) {
+                                               n = fread(buf, 1, sizeof(buf), 
fp);
+                                               if (n == 0) {
+                                                       eof = feof(fp);
                                                        if (myfd)
-                                                               (void)close(fd);
-                                                       if (n < 0) {
-                                                               free(record);
-                                                               return (-2);
-                                                       } else {
-                                                               fd = -1;
-                                                               eof = 1;
+                                                               
(void)fclose(fp);
+                                                       if (eof) {
+                                                               fp = NULL;
                                                                break;
                                                        }
+                                                       free(record);
+                                                       return (-2);
                                                }
                                                b_end = buf+n;
                                                bp = buf;
@@ -257,22 +269,22 @@
                                 * some more.
                                 */
                                if (rp >= r_end) {
-                                       u_int pos;
+                                       size_t off;
                                        size_t newsize;
 
-                                       pos = rp - record;
+                                       off = rp - record;
                                        newsize = r_end - record + BFRAG;
                                        s = realloc(record, newsize);
                                        if (s == NULL) {
                                                free(record);
                                                errno = ENOMEM;
                                                if (myfd)
-                                                       (void)close(fd);
+                                                       (void)fclose(fp);
                                                return (-2);
                                        }
                                        record = s;
                                        r_end = record + newsize;
-                                       rp = record + pos;
+                                       rp = record + off;
                                }
                        }
                        /* loop invariant lets us do this */
@@ -312,7 +324,7 @@
         * Got the capability record, but now we have to expand all use=name
         * references in it ...
         */
-       {
+exp_use: {
                char *newicap;
                int newilen;
                u_int ilen;
@@ -346,14 +358,14 @@
                        tclen = s - tcstart;
                        tcend = s;
 
-                       iret = getent(&icap, &ilen, db_p, fd, tc, depth+1);
+                       iret = getent(&icap, &ilen, db_p, fp, tc, depth+1);
                        newicap = icap;         /* Put into a register. */
                        newilen = ilen;
                        if (iret != 0) {
                                /* an error */
                                if (iret < -1) {
                                        if (myfd)
-                                               (void)close(fd);
+                                               (void)fclose(fp);
                                        free(record);
                                        return (iret);
                                }
@@ -388,27 +400,27 @@
                         */
                        diff = newilen - tclen;
                        if (diff >= r_end - rp) {
-                               u_int pos, tcpos, tcposend;
+                               size_t off, tcoff, tcoffend;
                                size_t newsize;
 
-                               pos = rp - record;
+                               off = rp - record;
                                newsize = r_end - record + diff + BFRAG;
-                               tcpos = tcstart - record;
-                               tcposend = tcend - record;
+                               tcoff = tcstart - record;
+                               tcoffend = tcend - record;
                                s = realloc(record, newsize);
                                if (s == NULL) {
                                        free(record);
                                        errno = ENOMEM;
                                        if (myfd)
-                                               (void)close(fd);
+                                               (void)fclose(fp);
                                        free(icap);
                                        return (-2);
                                }
                                record = s;
                                r_end = record + newsize;
-                               rp = record + pos;
-                               tcstart = record + tcpos;
-                               tcend = record + tcposend;
+                               rp = record + off;
+                               tcstart = record + tcoff;
+                               tcend = record + tcoffend;
                        }
 
                        /*
@@ -433,7 +445,7 @@
         * return capability, length and success.
         */
        if (myfd)
-               (void)close(fd);
+               (void)fclose(fp);
        *len = rp - record - 1; /* don't count NUL */
        if (r_end > rp) {
                if ((s =
@@ -515,107 +527,149 @@
  * upon returning an entry with more remaining, and -1 if an error occurs.
  */
 int
-igetnext(char **bp, char **db_array)
+igetnext(char **cap, char **db_array)
 {
-       size_t len;
-       int status, done;
-       char *cp, *line, *rp, *np, buf[BSIZE], nbuf[BSIZE];
-       u_int dummy;
+       int c, eof = 0, serrno, status = -1;
+       char buf[BUFSIZ];
+       char *b_end, *bp, *r_end, *rp;
+       char *record = NULL;
+       u_int len;
+       off_t pos;
 
        if (dbp == NULL)
                dbp = db_array;
 
-       if (pfp == NULL && (pfp = fopen(*dbp, "r")) == NULL) {
-               (void)igetclose();
-               return (-1);
-       }
+       if (pfp == NULL && (pfp = fopen(*dbp, "r")) == NULL)
+               goto done;
+
+       /*
+        * Allocate first chunk of memory.
+        */
+       if ((record = malloc(BFRAG)) == NULL)
+               goto done;
+       r_end = record + BFRAG;
+
+       /*
+        * Find the next capability record
+        */
+       /*
+        * Loop invariants:
+        *      There is always room for one more character in record.
+        *      R_end always points just past end of record.
+        *      Rp always points just past last character in record.
+        *      B_end always points just past last character in buf.
+        *      Bp always points at next character in buf.
+        */
+       b_end = buf;
+       bp = buf;
        for (;;) {
-               line = fgetln(pfp, &len);
-               if (line == NULL) {
-                       if (ferror(pfp)) {
-                               (void)igetclose();
-                               return (-1);
-                       } else {
-                               (void)fclose(pfp);
-                               pfp = NULL;
-                               if (*++dbp == NULL) {
-                                       (void)igetclose();
-                                       return (0);
-                               } else if ((pfp =
-                                   fopen(*dbp, "r")) == NULL) {
-                                       (void)igetclose();
-                                       return (-1);
-                               } else
-                                       continue;
+               /*
+                * If encountered EOF check next file.
+                */
+               if (eof) {
+                       (void)fclose(pfp);
+                       pfp = NULL;
+                       if (*++dbp == NULL) {
+                               status = 0;
+                               break;
                        }
-               } else
-                       line[len - 1] = '\0';/* XXX - assumes newline */
-               if (len == 1) {
-                       slash = 0;
-                       continue;
-               }
-               if (isspace(*line) ||
-                   *line == ',' || *line == '#' || slash) {
-                       if (line[len - 2] == '\\')
-                               slash = 1;
-                       else
-                               slash = 0;
-                       continue;
+                       if ((pfp = fopen(*dbp, "r")) == NULL)
+                               break;
+                       eof = 0;
                }
-               if (line[len - 2] == '\\')
-                       slash = 1;
-               else
-                       slash = 0;
 
                /*
-                * Line points to a name line.
+                * Read in a record implementing line continuation.
                 */
-               done = 0;
-               np = nbuf;
+               rp = record;
                for (;;) {
-                       for (cp = line; *cp != '\0'; cp++) {
-                               if (*cp == ',') {
-                                       *np++ = ',';
-                                       done = 1;
-                                       break;
+                       if (bp >= b_end) {
+                               size_t n;
+
+                               n = fread(buf, 1, sizeof(buf), pfp);
+                               if (n == 0) {
+                                       eof = feof(pfp);
+                                       if (eof)
+                                               break;
+                                       else
+                                               goto done;
                                }
-                               *np++ = *cp;
+                               b_end = buf + n;
+                               bp = buf;
                        }
-                       if (done) {
-                               *np = '\0';
-                               break;
-                       } else { /* name field extends beyond the line */
-                               line = fgetln(pfp, &len);
-                               if (line == NULL) {
-                                       if (ferror(pfp)) {
-                                               (void)igetclose();
-                                               return (-1);
+
+                       c = *bp++;
+                       if (c == '\n') {
+                               if (bp >= b_end) {
+                                       size_t n;
+
+                                       n = fread(buf, 1, sizeof(buf), pfp);
+                                       if (n == 0) {
+                                               eof = feof(pfp);
+                                               if (eof)
+                                                       break;
+                                               else
+                                                       goto done;
                                        }
-                                       /* Move on to next file. */
-                                       (void)fclose(pfp);
-                                       pfp = NULL;
-                                       ++dbp;
-                                       /* NUL terminate nbuf. */
-                                       *np = '\0';
+                                       b_end = buf + n;
+                                       bp = buf;
+                               }
+                               if (rp > record && isspace(*bp))
+                                       continue;
+                               else
                                        break;
-                               } else
-                                       /* XXX - assumes newline */
-                                       line[len - 1] = '\0';
+                       }
+                       if (rp <= record || *(rp - 1) != ',' || !isspace(c))
+                               *rp++ = c;
+
+                       /*
+                        * Enforce loop invariant: if no room
+                        * left in record buffer, try to get
+                        * some more.
+                        */
+                       if (rp >= r_end) {
+                               size_t newsize, off;
+                               char *nrecord;
+
+                               off = rp - record;
+                               newsize = r_end - record + BFRAG;
+                               nrecord = realloc(record, newsize);
+                               if (nrecord == NULL)
+                                       goto done;
+                               record = nrecord;
+                               r_end = record + newsize;
+                               rp = record + off;
                        }
                }
-               rp = buf;
-               for(cp = nbuf; *cp != '\0'; cp++)
-                       if (*cp == '|' || *cp == ',')
-                               break;
-                       else
-                               *rp++ = *cp;
+               /* loop invariant lets us do this */
+               *rp++ = '\0';
 
-               *rp = '\0';
-               status = getent(bp, &dummy, db_array, -1, buf, 0);
-               if (status == -2 || status == -3)
-                       (void)igetclose();
+               /*
+                * Toss blank lines and comments.
+                */
+               if (*record == '\0' || *record == '#')
+                       continue;
 
-               return (status + 1);
-       }
-       /* NOTREACHED */
+               /* rewind to end of record */
+               fseeko(pfp, (off_t)(bp - b_end), SEEK_CUR);
+
+               /* we pass the record to getent() in cap */
+               *cap = record;
+               len = rp - record;
+
+               /* return value of getent() is one less than igetnext() */
+               pos = ftello(pfp);
+               status = getent(cap, &len, dbp, pfp, NULL, 0) + 1;
+               if (status > 0)
+                       fseeko(pfp, pos, SEEK_SET);
+               break;
+       }
+done:
+       serrno = errno;
+       free(record);
+       if (status <= 0)
+               (void)igetclose();
+       errno = serrno;
+
+       return (status);
 }

Reply via email to