bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

gawk fix for VMS variable-length record filesystem problem


From: Aharon Robbins
Subject: gawk fix for VMS variable-length record filesystem problem
Date: Fri, 23 Sep 2005 16:15:40 +0300

Greetings all.

Below is a patch to gawk 3.1.5 for problems with VMS variable-length record
filesystems. Besides the change that provides the fix, this also includes
some new test scaffolding which may be useful in the future.

See the ChangeLog entry below for credit where credit is due.

Arnold Robbins
----------------------------------------------------------------------------
Fri Sep 23 16:05:13 2005  Arnold D. Robbins  <address@hidden>

        * awkgram.y (read_one_line): New function, mainly for debugging,
        that reads one line of data at a time to pass back as a buffer.
        Emulates the variable-length record filesystem of VMS, where
        we first saw the problem fixed here.
        (get_src_buf): New variable `readfunc' which is a pointer to a
        function implementing the `read' system call interface. Based on
        an environment variable, use `read_one_line' instead of `read'
        for testing.   Make the test for expanding the buffer smarter,
        so that it doesn't grow unnecessarily.

        Thanks to Galen Tackett (address@hidden) for reporting
        the problem and to Anders Wallin and Pat Rankin for help
        tracing and reproducing the problem and testing the fix.

--- ../gawk-3.1.5/awkgram.y     2005-07-26 21:07:43.000000000 +0300
+++ awkgram.y   2005-09-23 16:04:33.429126541 +0300
@@ -64,6 +64,8 @@
 static void func_use P((const char *name, enum defref how));
 static void check_funcs P((void));
 
+static ssize_t read_one_line P((int fd, void *buffer, size_t count));
+
 static int want_regexp;                /* lexical scanning kludge */
 static int can_return;         /* parsing kludge */
 static int begin_or_end_rule = FALSE;  /* parsing kludge */
@@ -1240,6 +1242,8 @@
        static size_t buflen = 0;
        static int fd;
 
+       static ssize_t (*readfunc)P((int fd, void *buffer, size_t count)) = 
NULL;
+
        int n;
        register char *scan;
        int newfile;
@@ -1248,6 +1252,16 @@
        int l;
        char *readloc;
 
+       if (readfunc == NULL) {
+               char *cp = getenv("AWKREADFUNC");
+
+               /* If necessary, one day, test value for different functions.  
*/
+               if (cp == NULL)
+                       readfunc = read;
+               else
+                       readfunc = read_one_line;
+       }
+
 again:
        newfile = FALSE;
        if (nextfile > numfiles)
@@ -1366,12 +1380,33 @@
                        }
                }
 
-               if (scan <= buf) {
+               /*
+                * This condition can be read as follows: IF
+                * 1. The beginning of the line is at the beginning of the
+                *    buffer (no newline was found: scan <= buf)
+                * AND:
+                *    2. The start of valid lexical data is into the buffer
+                *       (lexptr_begin > buf)
+                *       OR:
+                *       3. We have scanned past the end of the last data read
+                *          (lexptr == lexend)
+                *          AND:
+                *          4. There's no room left in the buffer
+                *             (lexptr_offset >= buflen - 2)
+                *
+                * If all that's true, grow the buffer to add more to
+                * the current line.
+                */
+
+               if (scan <= buf
+                   && (lexptr_begin > buf
+                       || (lexptr == lexend
+                           && lexptr_offset >= buflen - 2))) {
                        /* have to grow the buffer */
                        buflen *= 2;
                        erealloc(buf, char *, buflen, "get_src_buf");
-               } else {
-                       /* shift things down */
+               } else if (scan > buf) {
+                       /* Line starts in middle of the buffer, shift things 
down. */
                        memmove(buf, scan, lexend - scan);
                        /*
                         * make offsets relative to start of line,
@@ -1392,7 +1427,7 @@
        }
 
        /* add more data to buffer */
-       n = read(fd, readloc, readcount);
+       n = (*readfunc)(fd, readloc, readcount);
        if (n == -1)
                fatal(_("can't read sourcefile `%s' (%s)"),
                        source, strerror(errno));
@@ -3371,3 +3406,27 @@
        }
        return -1;
 }
+
+/* read_one_line --- return one input line at a time. mainly for debugging. */
+
+static ssize_t
+read_one_line(int fd, void *buffer, size_t count)
+{
+       static FILE *fp = NULL;
+       static char buf[BUFSIZ];
+
+       /* Minor potential memory leak here. Too bad. */
+       if (fp == NULL || fileno(fp) != fd) {
+               fp = fdopen(fd, "r");
+               if (fp == NULL) {
+                       fprintf(stderr, "ugh. fdopen: %s\n", strerror(errno));
+                       exit(1);
+               }
+       }
+
+       if (fgets(buf, sizeof buf, fp) == NULL)
+               return 0;
+
+       memcpy(buffer, buf, strlen(buf));
+       return strlen(buf);
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]