]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/Stdio/fparseln.c
StdLib/LibC/Stdio: fix "missing braces around initializer"
[mirror_edk2.git] / StdLib / LibC / Stdio / fparseln.c
CommitLineData
2aa62f2b 1/*\r
53e1e5c6 2 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
3 This program and the accompanying materials are licensed and made available\r
4 under the terms and conditions of the BSD License that accompanies this\r
5 distribution. The full text of the license may be found at\r
6 http://opensource.org/licenses/bsd-license.\r
7\r
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
10\r
2aa62f2b 11 * Copyright (c) 1997 Christos Zoulas. All rights reserved.\r
12 *\r
13 * Redistribution and use in source and binary forms, with or without\r
14 * modification, are permitted provided that the following conditions\r
15 * are met:\r
16 * 1. Redistributions of source code must retain the above copyright\r
17 * notice, this list of conditions and the following disclaimer.\r
18 * 2. Redistributions in binary form must reproduce the above copyright\r
19 * notice, this list of conditions and the following disclaimer in the\r
20 * documentation and/or other materials provided with the distribution.\r
21 * 3. All advertising materials mentioning features or use of this software\r
22 * must display the following acknowledgement:\r
23 * This product includes software developed by Christos Zoulas.\r
24 * 4. The name of the author may not be used to endorse or promote products\r
25 * derived from this software without specific prior written permission.\r
26 *\r
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
53e1e5c6 37\r
38 NetBSD: fparseln.c,v 1.5 2004/06/20 22:20:15 jmc Exp\r
39*/\r
2aa62f2b 40#include <LibConfig.h>\r
41#include <sys/EfiCdefs.h>\r
2aa62f2b 42\r
43#include "namespace.h"\r
44\r
45#include <assert.h>\r
46#include <errno.h>\r
47#include <stdio.h>\r
48#include <string.h>\r
49#include <stdlib.h>\r
50\r
51#ifdef __weak_alias\r
52__weak_alias(fparseln,_fparseln)\r
53#endif\r
54\r
55#if ! HAVE_FPARSELN\r
56\r
57#ifndef HAVE_NBTOOL_CONFIG_H\r
58#include "reentrant.h"\r
59#include "local.h"\r
60#else\r
61#define FLOCKFILE(fp)\r
62#define FUNLOCKFILE(fp)\r
63#endif\r
64\r
65#if defined(_REENTRANT) && !HAVE_NBTOOL_CONFIG_H\r
66#define __fgetln(f, l) __fgetstr(f, l, '\n')\r
67#else\r
68#define __fgetln(f, l) fgetln(f, l)\r
69#endif\r
70\r
71static int isescaped(const char *, const char *, int);\r
72\r
73/* isescaped():\r
74 * Return true if the character in *p that belongs to a string\r
75 * that starts in *sp, is escaped by the escape character esc.\r
76 */\r
77static int\r
78isescaped(const char *sp, const char *p, int esc)\r
79{\r
80 const char *cp;\r
81 size_t ne;\r
82\r
83 _DIAGASSERT(sp != NULL);\r
84 _DIAGASSERT(p != NULL);\r
85\r
86 /* No escape character */\r
87 if (esc == '\0')\r
88 return 1;\r
89\r
90 /* Count the number of escape characters that precede ours */\r
91 for (ne = 0, cp = p; --cp >= sp && *cp == esc; ne++)\r
92 continue;\r
93\r
94 /* Return true if odd number of escape characters */\r
95 return (ne & 1) != 0;\r
96}\r
97\r
98\r
99/* fparseln():\r
100 * Read a line from a file parsing continuations ending in \\r
101 * and eliminating trailing newlines, or comments starting with\r
102 * the comment char.\r
103 */\r
104char *\r
105fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)\r
106{\r
107 static const char dstr[3] = { '\\', '\\', '#' };\r
108\r
109 size_t s, len;\r
110 char *buf;\r
111 char *ptr, *cp;\r
112 int cnt;\r
113 char esc, con, nl, com;\r
114\r
115 _DIAGASSERT(fp != NULL);\r
53e1e5c6 116 if(fp == NULL) {\r
117 errno = EINVAL;\r
118 return (NULL);\r
119 }\r
2aa62f2b 120\r
121 len = 0;\r
122 buf = NULL;\r
123 cnt = 1;\r
124\r
125 if (str == NULL)\r
126 str = dstr;\r
127\r
128 esc = str[0];\r
129 con = str[1];\r
130 com = str[2];\r
131 /*\r
132 * XXX: it would be cool to be able to specify the newline character,\r
133 * but unfortunately, fgetln does not let us\r
134 */\r
135 nl = '\n';\r
136\r
137 FLOCKFILE(fp);\r
138\r
139 while (cnt) {\r
140 cnt = 0;\r
141\r
142 if (lineno)\r
143 (*lineno)++;\r
144\r
145 if ((ptr = __fgetln(fp, &s)) == NULL)\r
146 break;\r
147\r
148 if (s && com) { /* Check and eliminate comments */\r
149 for (cp = ptr; cp < ptr + s; cp++)\r
150 if (*cp == com && !isescaped(ptr, cp, esc)) {\r
151 s = cp - ptr;\r
152 cnt = s == 0 && buf == NULL;\r
153 break;\r
154 }\r
155 }\r
156\r
157 if (s && nl) { /* Check and eliminate newlines */\r
158 cp = &ptr[s - 1];\r
159\r
160 if (*cp == nl)\r
161 s--; /* forget newline */\r
162 }\r
163\r
164 if (s && con) { /* Check and eliminate continuations */\r
165 cp = &ptr[s - 1];\r
166\r
167 if (*cp == con && !isescaped(ptr, cp, esc)) {\r
168 s--; /* forget escape */\r
169 cnt = 1;\r
170 }\r
171 }\r
172\r
173 if (s == 0 && buf != NULL)\r
174 continue;\r
175\r
176 if ((cp = realloc(buf, len + s + 1)) == NULL) {\r
177 FUNLOCKFILE(fp);\r
178 free(buf);\r
179 return NULL;\r
180 }\r
181 buf = cp;\r
182\r
183 (void) memcpy(buf + len, ptr, s);\r
184 len += s;\r
185 buf[len] = '\0';\r
186 }\r
187\r
188 FUNLOCKFILE(fp);\r
189\r
190 if ((flags & FPARSELN_UNESCALL) != 0 && esc && buf != NULL &&\r
191 strchr(buf, esc) != NULL) {\r
192 ptr = cp = buf;\r
193 while (cp[0] != '\0') {\r
194 int skipesc;\r
195\r
196 while (cp[0] != '\0' && cp[0] != esc)\r
197 *ptr++ = *cp++;\r
198 if (cp[0] == '\0' || cp[1] == '\0')\r
199 break;\r
200\r
201 skipesc = 0;\r
202 if (cp[1] == com)\r
203 skipesc += (flags & FPARSELN_UNESCCOMM);\r
204 if (cp[1] == con)\r
205 skipesc += (flags & FPARSELN_UNESCCONT);\r
206 if (cp[1] == esc)\r
207 skipesc += (flags & FPARSELN_UNESCESC);\r
208 if (cp[1] != com && cp[1] != con && cp[1] != esc)\r
209 skipesc = (flags & FPARSELN_UNESCREST);\r
210\r
211 if (skipesc)\r
212 cp++;\r
213 else\r
214 *ptr++ = *cp++;\r
215 *ptr++ = *cp++;\r
216 }\r
217 *ptr = '\0';\r
218 len = strlen(buf);\r
219 }\r
220\r
221 if (size)\r
222 *size = len;\r
223 return buf;\r
224}\r
225\r
226#ifdef TEST\r
227\r
228int main(int, char **);\r
229\r
230int\r
231main(int argc, char **argv)\r
232{\r
233 char *ptr;\r
234 size_t size, line;\r
235\r
236 line = 0;\r
237 while ((ptr = fparseln(stdin, &size, &line, NULL,\r
238 FPARSELN_UNESCALL)) != NULL)\r
239 printf("line %d (%d) |%s|\n", line, size, ptr);\r
240 return 0;\r
241}\r
242\r
243/*\r
244\r
245# This is a test\r
246line 1\r
247line 2 \\r
248line 3 # Comment\r
249line 4 \# Not comment \\\\\r
250\r
251# And a comment \\r
252line 5 \\\\r
253line 6\r
254\r
255*/\r
256\r
257#endif /* TEST */\r
258#endif /* ! HAVE_FPARSELN */\r