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