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
__slbexpand(FILE * fp,size_t newsize)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 *
__fgetstr(FILE * fp,size_t * lenp,int sep)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