home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / dev / gcc / ixemulsrc.lha / ixemul / stdio / fgetln.c < prev    next >
C/C++ Source or Header  |  1996-12-11  |  5KB  |  168 lines

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