xkbcomp: Use fread() instead of getc()
authorDaniel Stone <daniel@fooishbar.org>
Tue, 15 Jun 2010 18:39:15 +0000 (19:39 +0100)
committerDaniel Stone <daniel@fooishbar.org>
Tue, 22 Jun 2010 14:56:56 +0000 (15:56 +0100)
So, it turns out that if you're parsing a fairly large amount of data,
using getc() to get all the input rather than, say, read(), is some kind
of remarkably daft and unperformant idea.

Signed-off-by: Daniel Stone <daniel@fooishbar.org>
src/xkbcomp/xkbscan.c

index a9eb23b..0490512 100644 (file)
@@ -46,9 +46,11 @@ int scanInt;
 char *scanStr = NULL;
 static int scanStrLine = 0;
 
-#define        BUFSIZE 512
+#define        BUFSIZE 4096
 static int nInBuf = 0;
-static char buf[BUFSIZE];
+static char readBuf[BUFSIZE];
+static int readBufPos = 0;
+static int readBufLen = 0;
 
 #ifdef DEBUG
 static char *
@@ -264,6 +266,32 @@ tokText(int tok)
 }
 #endif
 
+static char
+scanchar(void)
+{
+    if (readBufPos >= readBufLen) {
+        readBufLen = fread(readBuf, 1, BUFSIZE, yyin);
+        readBufPos = 0;
+        if (!readBufLen)
+            return EOF;
+        if (feof(yyin))
+            readBuf[readBufLen] = EOF;
+    }
+
+    return readBuf[readBufPos++];
+}
+
+static void
+unscanchar(char c)
+{
+    if (readBuf[--readBufPos] != c) {
+        fprintf(stderr, "UNGETCHAR FAILED! Put back %c, was expecting %c at "
+                        "position %d, buf is '%s'\n", c, readBuf[readBufPos],
+                        readBufPos, readBuf);
+        _exit(94);
+    }
+}
+
 int
 setScanState(char *file, int line)
 {
@@ -277,14 +305,15 @@ setScanState(char *file, int line)
 static int
 yyGetString(void)
 {
-    int ch;
+    int ch, i;
+    char buf[1024];
 
-    nInBuf = 0;
-    while (((ch = getc(yyin)) != EOF) && (ch != '"'))
+    i = 0;
+    while (((ch = scanchar()) != EOF) && (ch != '"'))
     {
         if (ch == '\\')
         {
-            if ((ch = getc(yyin)) != EOF)
+            if ((ch = scanchar()) != EOF)
             {
                 if (ch == 'n')
                     ch = '\n';
@@ -304,7 +333,7 @@ yyGetString(void)
                 {
                     int tmp, stop;
                     ch = stop = 0;
-                    if (((tmp = getc(yyin)) != EOF) && (isdigit(tmp))
+                    if (((tmp = scanchar()) != EOF) && (isdigit(tmp))
                         && (tmp != '8') && (tmp != '9'))
                     {
                         ch = (ch * 8) + (tmp - '0');
@@ -312,11 +341,11 @@ yyGetString(void)
                     else
                     {
                         stop = 1;
-                        ungetc(tmp, yyin);
+                        unscanchar(tmp);
                     }
                     if (!stop)
                     {
-                        if (((tmp = getc(yyin)) != EOF)
+                        if (((tmp = scanchar()) != EOF)
                             && (isdigit(tmp)) && (tmp != '8') && (tmp != '9'))
                         {
                             ch = (ch * 8) + (tmp - '0');
@@ -324,12 +353,12 @@ yyGetString(void)
                         else
                         {
                             stop = 1;
-                            ungetc(tmp, yyin);
+                            unscanchar(tmp);
                         }
                     }
                     if (!stop)
                     {
-                        if (((tmp = getc(yyin)) != EOF)
+                        if (((tmp = scanchar()) != EOF)
                             && (isdigit(tmp)) && (tmp != '8') && (tmp != '9'))
                         {
                             ch = (ch * 8) + (tmp - '0');
@@ -337,7 +366,7 @@ yyGetString(void)
                         else
                         {
                             stop = 1;
-                            ungetc(tmp, yyin);
+                            unscanchar(tmp);
                         }
                     }
                 }
@@ -345,12 +374,12 @@ yyGetString(void)
             else
                 return ERROR_TOK;
         }
-        if (nInBuf < BUFSIZE - 1)
-            buf[nInBuf++] = ch;
+        if (i < sizeof(buf) - 1)
+            buf[i++] = ch;
     }
     if (ch == '"')
     {
-        buf[nInBuf++] = '\0';
+        buf[i++] = '\0';
         if (scanStr)
             uFree(scanStr);
         scanStr = strdup(buf);
@@ -363,14 +392,15 @@ yyGetString(void)
 static int
 yyGetKeyName(void)
 {
-    int ch;
+    int ch, i;
+    char buf[1024];
 
-    nInBuf = 0;
-    while (((ch = getc(yyin)) != EOF) && (ch != '>'))
+    i = 0;
+    while (((ch = scanchar()) != EOF) && (ch != '>'))
     {
         if (ch == '\\')
         {
-            if ((ch = getc(yyin)) != EOF)
+            if ((ch = scanchar()) != EOF)
             {
                 if (ch == 'n')
                     ch = '\n';
@@ -390,7 +420,7 @@ yyGetKeyName(void)
                 {
                     int tmp, stop;
                     ch = stop = 0;
-                    if (((tmp = getc(yyin)) != EOF) && (isdigit(tmp))
+                    if (((tmp = scanchar()) != EOF) && (isdigit(tmp))
                         && (tmp != '8') && (tmp != '9'))
                     {
                         ch = (ch * 8) + (tmp - '0');
@@ -398,9 +428,9 @@ yyGetKeyName(void)
                     else
                     {
                         stop = 1;
-                        ungetc(tmp, yyin);
+                        unscanchar(tmp);
                     }
-                    if ((!stop) && ((tmp = getc(yyin)) != EOF)
+                    if ((!stop) && ((tmp = scanchar()) != EOF)
                         && (isdigit(tmp)) && (tmp != '8') && (tmp != '9'))
                     {
                         ch = (ch * 8) + (tmp - '0');
@@ -408,9 +438,9 @@ yyGetKeyName(void)
                     else
                     {
                         stop = 1;
-                        ungetc(tmp, yyin);
+                        unscanchar(tmp);
                     }
-                    if ((!stop) && ((tmp = getc(yyin)) != EOF)
+                    if ((!stop) && ((tmp = scanchar()) != EOF)
                         && (isdigit(tmp)) && (tmp != '8') && (tmp != '9'))
                     {
                         ch = (ch * 8) + (tmp - '0');
@@ -418,7 +448,7 @@ yyGetKeyName(void)
                     else
                     {
                         stop = 1;
-                        ungetc(tmp, yyin);
+                        unscanchar(tmp);
                     }
                 }
             }
@@ -426,12 +456,12 @@ yyGetKeyName(void)
                 return ERROR_TOK;
         }
 
-        if (nInBuf < BUFSIZE - 1)
-            buf[nInBuf++] = ch;
+        if (i < sizeof(buf) - 1)
+            buf[i++] = ch;
     }
-    if ((ch == '>') && (nInBuf < 5))
+    if ((ch == '>') && (i < 5))
     {
-        buf[nInBuf++] = '\0';
+        buf[i++] = '\0';
         if (scanStr)
             uFree(scanStr);
         scanStr = strdup(buf);
@@ -543,17 +573,18 @@ static int numKeywords = sizeof(keywords) / sizeof(struct _Keyword);
 static int
 yyGetIdent(int first)
 {
-    int ch, i, found;
+    int ch, i, j, found;
     int rtrn = IDENT;
+    char buf[1024];
 
     buf[0] = first;
-    nInBuf = 1;
-    while (((ch = getc(yyin)) != EOF) && (isalnum(ch) || (ch == '_')))
+    j = 1;
+    while (((ch = scanchar()) != EOF) && (isalnum(ch) || (ch == '_')))
     {
-        if (nInBuf < BUFSIZE - 1)
-            buf[nInBuf++] = ch;
+        if (j < sizeof(buf) - 1)
+            buf[j++] = ch;
     }
-    buf[nInBuf++] = '\0';
+    buf[j++] = '\0';
     found = 0;
 
     for (i = 0; (!found) && (i < numKeywords); i++)
@@ -574,7 +605,7 @@ yyGetIdent(int first)
     }
 
     if ((ch != EOF) && (!isspace(ch)))
-        ungetc(ch, yyin);
+        unscanchar(ch);
     else if (ch == '\n')
         lineNum++;
 
@@ -585,10 +616,11 @@ static int
 yyGetNumber(int ch)
 {
     int isFloat = 0;
+    char buf[1024];
 
     buf[0] = ch;
     nInBuf = 1;
-    while (((ch = getc(yyin)) != EOF)
+    while (((ch = scanchar()) != EOF)
            && (isxdigit(ch) || ((nInBuf == 1) && (ch == 'x'))))
     {
         buf[nInBuf++] = ch;
@@ -597,14 +629,14 @@ yyGetNumber(int ch)
     {
         isFloat = 1;
         buf[nInBuf++] = ch;
-        while (((ch = getc(yyin)) != EOF) && (isxdigit(ch)))
+        while (((ch = scanchar()) != EOF) && (isxdigit(ch)))
         {
             buf[nInBuf++] = ch;
         }
     }
     buf[nInBuf++] = '\0';
     if ((ch != EOF) && (!isspace(ch)))
-        ungetc(ch, yyin);
+        unscanchar(ch);
 
     if (isFloat)
     {
@@ -629,7 +661,7 @@ yylex(void)
 
     do
     {
-        ch = getc(yyin);
+        ch = scanchar();
         if (ch == '\n')
         {
             lineNum++;
@@ -638,26 +670,26 @@ yylex(void)
         {                       /* handle shell style '#' comments */
             do
             {
-                ch = getc(yyin);
+                ch = scanchar();
             }
             while ((ch != '\n') && (ch != EOF));
             lineNum++;
         }
         else if (ch == '/')
         {                       /* handle C++ style double-/ comments */
-            int newch = getc(yyin);
+            int newch = scanchar();
             if (newch == '/')
             {
                 do
                 {
-                    ch = getc(yyin);
+                    ch = scanchar();
                 }
                 while ((ch != '\n') && (ch != EOF));
                 lineNum++;
             }
             else if (newch != EOF)
             {
-                ungetc(newch, yyin);
+                unscanchar(newch);
             }
         }
     }