interface change: size parameter is required, keep newline;
authorChris Torek <torek@ucbvax.Berkeley.EDU>
Thu, 4 Mar 1993 07:28:56 +0000 (23:28 -0800)
committerChris Torek <torek@ucbvax.Berkeley.EDU>
Thu, 4 Mar 1993 07:28:56 +0000 (23:28 -0800)
no longer returns a C string (callers must use care)

SCCS-vsn: lib/libc/stdio/fgetln.3 5.5
SCCS-vsn: lib/libc/stdio/fgetln.c 5.3

usr/src/lib/libc/stdio/fgetln.3
usr/src/lib/libc/stdio/fgetln.c

index 08420ff..87be425 100644 (file)
@@ -3,7 +3,7 @@
 .\"
 .\" %sccs.include.redist.man%
 .\"
 .\"
 .\" %sccs.include.redist.man%
 .\"
-.\"     @(#)fgetln.3   5.4 (Berkeley) %G%
+.\"     @(#)fgetln.3   5.5 (Berkeley) %G%
 .\"
 .Dd 
 .Dt FGETLINE 3
 .\"
 .Dd 
 .Dt FGETLINE 3
@@ -21,14 +21,18 @@ The
 function
 returns a pointer to the next line from the stream referenced by
 .Fa stream .
 function
 returns a pointer to the next line from the stream referenced by
 .Fa stream .
-The newline character at the end of the line is replaced by a
-.Dv NUL .
-.Pp
-If
+This line is
+.Em not
+a C string as it does not end with a terminating
+.Dv NUL
+character.
+The length of the line, including the final newline,
+is stored in the memory location to which
 .Fa len
 .Fa len
-is non-NULL, the length of the line, not counting the terminating
-.Dv NUL ,
-is stored in the memory location it references.
+points.
+(Note, however, that if the line is the last
+in a file that does not end in a newline,
+the returned text will not contain a newline.)
 .Sh RETURN VALUES
 Upon successful completion a pointer is returned;
 this pointer becomes invalid after the next
 .Sh RETURN VALUES
 Upon successful completion a pointer is returned;
 this pointer becomes invalid after the next
@@ -60,8 +64,7 @@ cleared with
 .Xr clearerr 3 .
 .Pp
 The text to which the returned pointer points may be modified,
 .Xr clearerr 3 .
 .Pp
 The text to which the returned pointer points may be modified,
-provided that no changes are made beyond the terminating
-.Dv NUL .
+provided that no changes are made beyond the returned size.
 These changes are lost as soon as the pointer becomes invalid.
 .Sh ERRORS
 .Bl -tag -width [EBADF]
 These changes are lost as soon as the pointer becomes invalid.
 .Sh ERRORS
 .Bl -tag -width [EBADF]
@@ -93,6 +96,3 @@ The
 .Fn fgetline
 function is
 .Ud .
 .Fn fgetline
 function is
 .Ud .
-.Sh BUGS
-It is not possible to tell whether the final line of an input file
-was terminated with a newline.
index c33837e..6e813be 100644 (file)
@@ -9,7 +9,7 @@
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)fgetln.c   5.2 (Berkeley) %G%";
+static char sccsid[] = "@(#)fgetln.c   5.3 (Berkeley) %G%";
 #endif /* LIBC_SCCS and not lint */
 
 #include <stdio.h>
 #endif /* LIBC_SCCS and not lint */
 
 #include <stdio.h>
@@ -19,8 +19,10 @@ static char sccsid[] = "@(#)fgetln.c 5.2 (Berkeley) %G%";
 
 /*
  * Expand the line buffer.  Return -1 on error.
 
 /*
  * Expand the line buffer.  Return -1 on error.
+#ifdef notdef
  * The `new size' does not account for a terminating '\0',
  * so we add 1 here.
  * The `new size' does not account for a terminating '\0',
  * so we add 1 here.
+#endif
  */
 __slbexpand(fp, newsize)
        FILE *fp;
  */
 __slbexpand(fp, newsize)
        FILE *fp;
@@ -28,7 +30,10 @@ __slbexpand(fp, newsize)
 {
        void *p;
 
 {
        void *p;
 
-       if (fp->_lb._size >= ++newsize)
+#ifdef notdef
+       ++newsize;
+#endif
+       if (fp->_lb._size >= newsize)
                return (0);
        if ((p = realloc(fp->_lb._base, newsize)) == NULL)
                return (-1);
                return (0);
        if ((p = realloc(fp->_lb._base, newsize)) == NULL)
                return (-1);
@@ -39,9 +44,10 @@ __slbexpand(fp, newsize)
 
 /*
  * Get an input line.  The returned pointer often (but not always)
 
 /*
  * Get an input line.  The returned pointer often (but not always)
- * points into a stdio buffer.  Fgetline smashes the newline (if any)
- * in the stdio buffer; callers must not use it on streams that
- * have `magic' setvbuf() games happening.
+ * points into a stdio buffer.  Fgetline does not alter the text of
+ * the returned line (which is thus not a C string because it will
+ * not necessarily end with '\0'), but does allow callers to modify
+ * it if they wish.  Thus, we set __SMOD in case the caller does.
  */
 char *
 fgetline(fp, lenp)
  */
 char *
 fgetline(fp, lenp)
@@ -54,8 +60,7 @@ fgetline(fp, lenp)
 
        /* make sure there is input */
        if (fp->_r <= 0 && __srefill(fp)) {
 
        /* make sure there is input */
        if (fp->_r <= 0 && __srefill(fp)) {
-               if (lenp != NULL)
-                       *lenp = 0;
+               *lenp = 0;
                return (NULL);
        }
 
                return (NULL);
        }
 
@@ -64,31 +69,26 @@ fgetline(fp, lenp)
                register char *ret;
 
                /*
                register char *ret;
 
                /*
-                * Found one.  Flag buffer as modified to keep
-                * fseek from `optimising' a backward seek, since
-                * the newline is about to be trashed.  (We should
-                * be able to get away with doing this only if
-                * p is not pointing into an ungetc buffer, since
-                * fseek discards ungetc data, but this is the
-                * usual case anyway.)
+                * Found one.  Flag buffer as modified to keep fseek from
+                * `optimising' a backward seek, in case the user stomps on
+                * the text.
                 */
                 */
+               p++;            /* advance over it */
                ret = (char *)fp->_p;
                ret = (char *)fp->_p;
-               len = p - fp->_p;
+               *lenp = len = p - fp->_p;
                fp->_flags |= __SMOD;
                fp->_flags |= __SMOD;
-               *p = 0;
-               fp->_r -= len + 1;
-               fp->_p = p + 1;
-               if (lenp != NULL)
-                       *lenp = len;
+               fp->_r -= len;
+               fp->_p = p;
                return (ret);
        }
 
        /*
         * We have to copy the current buffered data to the line buffer.
                return (ret);
        }
 
        /*
         * We have to copy the current buffered data to the line buffer.
+        * As a bonus, though, we can leave off the __SMOD.
         *
         *
-        * OPTIMISTIC is length that we (optimistically)
-        * expect will accomodate the `rest' of the string,
-        * on each trip through the loop below.
+        * OPTIMISTIC is length that we (optimistically) expect will
+        * accomodate the `rest' of the string, on each trip through the
+        * loop below.
         */
 #define OPTIMISTIC 80
 
         */
 #define OPTIMISTIC 80
 
@@ -96,14 +96,13 @@ fgetline(fp, lenp)
                register size_t diff;
 
                /*
                register size_t diff;
 
                /*
-                * Make sure there is room for more bytes.
-                * Copy data from file buffer to line buffer,
-                * refill file and look for newline.  The
-                * loop stops only when we find a newline.
+                * Make sure there is room for more bytes.  Copy data from
+                * file buffer to line buffer, refill file and look for
+                * newline.  The loop stops only when we find a newline.
                 */
                if (__slbexpand(fp, len + OPTIMISTIC))
                        goto error;
                 */
                if (__slbexpand(fp, len + OPTIMISTIC))
                        goto error;
-               (void) bcopy((void *)fp->_p, (void *)(fp->_lb._base + off),
+               (void)bcopy((void *)fp->_p, (void *)(fp->_lb._base + off),
                    len - off);
                off = len;
                if (__srefill(fp))
                    len - off);
                off = len;
                if (__srefill(fp))
@@ -112,24 +111,24 @@ fgetline(fp, lenp)
                        continue;
 
                /* got it: finish up the line (like code above) */
                        continue;
 
                /* got it: finish up the line (like code above) */
-               fp->_flags |= __SMOD;   /* soon */
+               p++;
                diff = p - fp->_p;
                len += diff;
                if (__slbexpand(fp, len))
                        goto error;
                diff = p - fp->_p;
                len += diff;
                if (__slbexpand(fp, len))
                        goto error;
-               (void) bcopy((void *)fp->_p, (void *)(fp->_lb._base + off),
+               (void)bcopy((void *)fp->_p, (void *)(fp->_lb._base + off),
                    diff);
                    diff);
-               fp->_r -= diff + 1;
-               fp->_p = p + 1;
+               fp->_r -= diff;
+               fp->_p = p;
                break;
        }
                break;
        }
-       if (lenp != NULL)
-               *lenp = len;
+       *lenp = len;
+#ifdef notdef
        fp->_lb._base[len] = 0;
        fp->_lb._base[len] = 0;
+#endif
        return ((char *)fp->_lb._base);
 
 error:
        return ((char *)fp->_lb._base);
 
 error:
-       if (lenp != NULL)
-               *lenp = 0;      /* ??? */
+       *lenp = 0;              /* ??? */
        return (NULL);          /* ??? */
 }
        return (NULL);          /* ??? */
 }