fgetln.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       fgetln.c (4848B)
       ---
            1 /*-
            2  * Copyright (c) 1990, 1993
            3  *        The Regents of the University of California.  All rights reserved.
            4  *
            5  * This code is derived from software contributed to Berkeley by
            6  * Chris Torek.
            7  *
            8  * Redistribution and use in source and binary forms, with or without
            9  * modification, are permitted provided that the following conditions
           10  * are met:
           11  * 1. Redistributions of source code must retain the above copyright
           12  *    notice, this list of conditions and the following disclaimer.
           13  * 2. Redistributions in binary form must reproduce the above copyright
           14  *    notice, this list of conditions and the following disclaimer in the
           15  *    documentation and/or other materials provided with the distribution.
           16  * 3. All advertising materials mentioning features or use of this software
           17  *    must display the following acknowledgement:
           18  *        This product includes software developed by the University of
           19  *        California, Berkeley and its contributors.
           20  * 4. Neither the name of the University nor the names of its contributors
           21  *    may be used to endorse or promote products derived from this software
           22  *    without specific prior written permission.
           23  *
           24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
           25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
           26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
           27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
           28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
           29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
           30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
           31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
           32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
           33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
           34  * SUCH DAMAGE.
           35  */
           36 
           37 #if defined(LIBC_SCCS) && !defined(lint)
           38 static char *rcsid = "$OpenBSD: fgetln.c,v 1.2 1996/08/19 08:32:29 tholo Exp $";
           39 #endif /* LIBC_SCCS and not lint */
           40 
           41 #include <stdio.h>
           42 #include <stdlib.h>
           43 #include <string.h>
           44 #include "local.h"
           45 
           46 /*
           47  * Expand the line buffer.  Return -1 on error.
           48 #ifdef notdef
           49  * The `new size' does not account for a terminating '\0',
           50  * so we add 1 here.
           51 #endif
           52  */
           53 int
           54 __slbexpand(fp, newsize)
           55         FILE *fp;
           56         size_t newsize;
           57 {
           58         void *p;
           59 
           60 #ifdef notdef
           61         ++newsize;
           62 #endif
           63         if (fp->_lb._size >= newsize)
           64                 return (0);
           65         if ((p = realloc(fp->_lb._base, newsize)) == NULL)
           66                 return (-1);
           67         fp->_lb._base = p;
           68         fp->_lb._size = newsize;
           69         return (0);
           70 }
           71 
           72 /*
           73  * Get an input line.  The returned pointer often (but not always)
           74  * points into a stdio buffer.  Fgetline does not alter the text of
           75  * the returned line (which is thus not a C string because it will
           76  * not necessarily end with '\0'), but does allow callers to modify
           77  * it if they wish.  Thus, we set __SMOD in case the caller does.
           78  */
           79 char *
           80 fgetln(fp, lenp)
           81         register FILE *fp;
           82         size_t *lenp;
           83 {
           84         register unsigned char *p;
           85         register size_t len;
           86         size_t off;
           87 
           88         /* make sure there is input */
           89         if (fp->_r <= 0 && __srefill(fp)) {
           90                 *lenp = 0;
           91                 return (NULL);
           92         }
           93 
           94         /* look for a newline in the input */
           95         if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) {
           96                 register char *ret;
           97 
           98                 /*
           99                  * Found one.  Flag buffer as modified to keep fseek from
          100                  * `optimising' a backward seek, in case the user stomps on
          101                  * the text.
          102                  */
          103                 p++;                /* advance over it */
          104                 ret = (char *)fp->_p;
          105                 *lenp = len = p - fp->_p;
          106                 fp->_flags |= __SMOD;
          107                 fp->_r -= len;
          108                 fp->_p = p;
          109                 return (ret);
          110         }
          111 
          112         /*
          113          * We have to copy the current buffered data to the line buffer.
          114          * As a bonus, though, we can leave off the __SMOD.
          115          *
          116          * OPTIMISTIC is length that we (optimistically) expect will
          117          * accomodate the `rest' of the string, on each trip through the
          118          * loop below.
          119          */
          120 #define OPTIMISTIC 80
          121 
          122         for (len = fp->_r, off = 0;; len += fp->_r) {
          123                 register size_t diff;
          124 
          125                 /*
          126                  * Make sure there is room for more bytes.  Copy data from
          127                  * file buffer to line buffer, refill file and look for
          128                  * newline.  The loop stops only when we find a newline.
          129                  */
          130                 if (__slbexpand(fp, len + OPTIMISTIC))
          131                         goto error;
          132                 (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
          133                     len - off);
          134                 off = len;
          135                 if (__srefill(fp))
          136                         break;        /* EOF or error: return partial line */
          137                 if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL)
          138                         continue;
          139 
          140                 /* got it: finish up the line (like code above) */
          141                 p++;
          142                 diff = p - fp->_p;
          143                 len += diff;
          144                 if (__slbexpand(fp, len))
          145                         goto error;
          146                 (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
          147                     diff);
          148                 fp->_r -= diff;
          149                 fp->_p = p;
          150                 break;
          151         }
          152         *lenp = len;
          153 #ifdef notdef
          154         fp->_lb._base[len] = 0;
          155 #endif
          156         return ((char *)fp->_lb._base);
          157 
          158 error:
          159         *lenp = 0;                /* ??? */
          160         return (NULL);                /* ??? */
          161 }