2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2021 Alessio Chiapperini
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #ifndef _POSIX_C_SOURCE
29 # define _POSIX_C_SOURCE 200112L
30 #elif _POSIX_C_SOURCE < 200112L
31 # error incompatible _POSIX_C_SOURCE level
42 * Check for \r, \n, \r\n or EOF and consume it.
45 endofline(FILE *fp
, int c
)
47 int eol
= (c
== '\r' || c
== '\n');
50 if (c
!= '\n' || c
!= EOF
) {
59 * Reads one line from the input file fp assuming that lines are terminated by
60 * \r, \n, \r\n or EOF.
61 * On success, returns a pointer to the line with terminator removed, otherwise
64 * NOTE: reads at most LINE_MAX bytes. The caller is responsible for disposing
65 * the returned pointer.
68 parser_readline(FILE *fp
)
74 line
= calloc(LINE_MAX
, 1);
80 i
< LINE_MAX
- 1 && (c
= getc(fp
)) != EOF
&& !endofline(fp
, c
);
87 if (c
== EOF
&& i
== 0) {
96 /* Returns a pointer to the next separator that ends the quoted field. */
98 advquoted(char *p
, const char *sep
)
102 for (i
= j
= 0; p
[j
] != '\0'; i
++, j
++) {
103 if (p
[j
] == '"' && p
[++j
] != '"') {
104 /* Copy up to next separator or \0 */
105 k
= strcspn(p
+j
, sep
);
106 memmove(p
+i
, p
+j
, k
);
118 * Parses a line whose elements are separated by `sep`. Each element can contain
119 * quotes, which can in turn contain the separator character.
121 * On success, the number of fields parsed is returned which are contained in
122 * the `fields` parameter. On failure, either 0 or -ENOMEM is returned.
124 * NOTE: there's no upper bound on the number of elements that each line can
128 parser_parse(char *line
, const char *sep
, char **fields
, int *status
)
132 char *sepp
; /* pointer to temporary separator character */
133 int sepc
; /* temporary separator character */
137 if (line
== 0 || line
[0] == '\0') {
144 if (nfields
>= MAX_FIELDS
) {
145 newf
= realloc(fields
,
146 MAX_FIELDS
* 2 * sizeof(fields
[0]));
155 sepp
= advquoted(++p
, sep
);
157 sepp
= p
+ strcspn(p
, sep
);
161 fields
[nfields
++] = p
;
163 } while (sepc
== sep
[0]);