1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include "libbb.h"
34
35#if defined ENABLE_PARSE && ENABLE_PARSE
36int parse_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
37int parse_main(int argc UNUSED_PARAM, char **argv)
38{
39 const char *delims = "# \t";
40 char **t;
41 unsigned flags = PARSE_NORMAL;
42 int mintokens = 0, ntokens = 128;
43 unsigned noout;
44
45 noout = 1 & getopt32(argv, "^" "xn:+m:+d:f:+" "\0" "-1",
46 &ntokens, &mintokens, &delims, &flags
47 );
48
49 argv += optind;
50
51 t = xmalloc(sizeof(t[0]) * ntokens);
52 while (*argv) {
53 int n;
54 parser_t *p = config_open(*argv);
55 while ((n = config_read(p, t, ntokens, mintokens, delims, flags)) != 0) {
56 if (!noout) {
57 for (int i = 0; i < n; ++i)
58 printf("[%s]", t[i]);
59 puts("");
60 }
61 }
62 config_close(p);
63 argv++;
64 }
65 return EXIT_SUCCESS;
66}
67#endif
68
69parser_t* FAST_FUNC config_open2(const char *filename, FILE* FAST_FUNC (*fopen_func)(const char *path))
70{
71 FILE* fp;
72 parser_t *parser;
73
74 fp = fopen_func(filename);
75 if (!fp)
76 return NULL;
77 parser = xzalloc(sizeof(*parser));
78 parser->fp = fp;
79 return parser;
80}
81
82parser_t* FAST_FUNC config_open(const char *filename)
83{
84 return config_open2(filename, fopen_or_warn_stdin);
85}
86
87void FAST_FUNC config_close(parser_t *parser)
88{
89 if (parser) {
90 if (PARSE_KEEP_COPY)
91 free(parser->data);
92 fclose(parser->fp);
93 free(parser->line);
94 free(parser->nline);
95 free(parser);
96 }
97}
98
99
100
101
102
103
104static int get_line_with_continuation(parser_t *parser)
105{
106 ssize_t len, nlen;
107 char *line;
108
109 len = getline(&parser->line, &parser->line_alloc, parser->fp);
110 if (len <= 0)
111 return len;
112
113 line = parser->line;
114 for (;;) {
115 parser->lineno++;
116 if (line[len - 1] == '\n')
117 len--;
118 if (len == 0 || line[len - 1] != '\\')
119 break;
120 len--;
121
122 nlen = getline(&parser->nline, &parser->nline_alloc, parser->fp);
123 if (nlen <= 0)
124 break;
125
126 if (parser->line_alloc < len + nlen + 1) {
127 parser->line_alloc = len + nlen + 1;
128 line = parser->line = xrealloc(line, parser->line_alloc);
129 }
130 memcpy(&line[len], parser->nline, nlen);
131 len += nlen;
132 }
133
134 line[len] = '\0';
135 return len;
136}
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162#undef config_read
163int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims)
164{
165 char *line, *p;
166 int ntokens, mintokens;
167 int t;
168 char alt_comment_ch;
169
170 if (!parser)
171 return 0;
172
173 alt_comment_ch = '\0';
174 if (flags & PARSE_ALT_COMMENTS)
175 alt_comment_ch = *delims++;
176
177 ntokens = (uint8_t)flags;
178 mintokens = (uint8_t)(flags >> 8);
179
180 again:
181 memset(tokens, 0, sizeof(tokens[0]) * ntokens);
182
183
184 if (get_line_with_continuation(parser) < 0)
185 return 0;
186
187 line = parser->line;
188
189
190 if (flags & PARSE_TRIM)
191 line += strspn(line, delims + 1);
192
193 p = line;
194 if (flags & PARSE_WS_COMMENTS)
195 p = skip_whitespace(p);
196 if (p[0] == '\0' || p[0] == delims[0] || p[0] == alt_comment_ch)
197 goto again;
198
199 if (flags & PARSE_KEEP_COPY) {
200 free(parser->data);
201 parser->data = xstrdup(line);
202 }
203
204
205 t = 0;
206 do {
207
208 tokens[t] = line;
209
210
211 if ((t != (ntokens-1)) || !(flags & PARSE_GREEDY)) {
212
213 line += strcspn(line, (delims[0] && (flags & PARSE_EOL_COMMENTS)) ? delims : delims + 1);
214 } else {
215
216 line = strchrnul(line, (flags & PARSE_EOL_COMMENTS) ? delims[0] : '\0');
217
218
219 if (flags & PARSE_TRIM) {
220 while (strchr(delims + 1, line[-1]) != NULL)
221 line--;
222 }
223 }
224
225
226 if ((flags & PARSE_EOL_COMMENTS) && *line == delims[0])
227 *line = '\0';
228 else if (*line != '\0')
229 *line++ = '\0';
230
231#if 0
232 if (flags & PARSE_ESCAPE) {
233 strcpy_and_process_escape_sequences(tokens[t], tokens[t]);
234 }
235#endif
236
237 if (flags & PARSE_COLLAPSE)
238 line += strspn(line, delims + 1);
239
240 t++;
241 } while (*line && *line != delims[0] && t < ntokens);
242
243 if (t < mintokens) {
244 bb_error_msg("bad line %u: %d tokens found, %d needed",
245 parser->lineno, t, mintokens);
246 if (flags & PARSE_MIN_DIE)
247 xfunc_die();
248 goto again;
249 }
250
251 return t;
252}
253