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 opt_complementary = "-1:n+:m+:f+";
46 noout = 1 & getopt32(argv, "xn:m:d:f:", &ntokens, &mintokens, &delims, &flags);
47
48 argv += optind;
49
50 t = xmalloc(sizeof(t[0]) * ntokens);
51 while (*argv) {
52 int n;
53 parser_t *p = config_open(*argv);
54 while ((n = config_read(p, t, ntokens, mintokens, delims, flags)) != 0) {
55 if (!noout) {
56 for (int i = 0; i < n; ++i)
57 printf("[%s]", t[i]);
58 puts("");
59 }
60 }
61 config_close(p);
62 argv++;
63 }
64 return EXIT_SUCCESS;
65}
66#endif
67
68parser_t* FAST_FUNC config_open2(const char *filename, FILE* FAST_FUNC (*fopen_func)(const char *path))
69{
70 FILE* fp;
71 parser_t *parser;
72
73 fp = fopen_func(filename);
74 if (!fp)
75 return NULL;
76 parser = xzalloc(sizeof(*parser));
77 parser->fp = fp;
78 return parser;
79}
80
81parser_t* FAST_FUNC config_open(const char *filename)
82{
83 return config_open2(filename, fopen_or_warn_stdin);
84}
85
86void FAST_FUNC config_close(parser_t *parser)
87{
88 if (parser) {
89 if (PARSE_KEEP_COPY)
90 free(parser->data);
91 fclose(parser->fp);
92 free(parser->line);
93 free(parser->nline);
94 free(parser);
95 }
96}
97
98
99
100
101
102
103static int get_line_with_continuation(parser_t *parser)
104{
105 ssize_t len, nlen;
106 char *line;
107
108 len = getline(&parser->line, &parser->line_alloc, parser->fp);
109 if (len <= 0)
110 return len;
111
112 line = parser->line;
113 for (;;) {
114 parser->lineno++;
115 if (line[len - 1] == '\n')
116 len--;
117 if (len == 0 || line[len - 1] != '\\')
118 break;
119 len--;
120
121 nlen = getline(&parser->nline, &parser->nline_alloc, parser->fp);
122 if (nlen <= 0)
123 break;
124
125 if (parser->line_alloc < len + nlen + 1) {
126 parser->line_alloc = len + nlen + 1;
127 line = parser->line = xrealloc(line, parser->line_alloc);
128 }
129 memcpy(&line[len], parser->nline, nlen);
130 len += nlen;
131 }
132
133 line[len] = '\0';
134 return len;
135}
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#undef config_read
162int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims)
163{
164 char *line;
165 int ntokens, mintokens;
166 int t;
167
168 if (!parser)
169 return 0;
170
171 ntokens = (uint8_t)flags;
172 mintokens = (uint8_t)(flags >> 8);
173
174 again:
175 memset(tokens, 0, sizeof(tokens[0]) * ntokens);
176
177
178 if (get_line_with_continuation(parser) < 0)
179 return 0;
180
181 line = parser->line;
182
183
184 if (flags & PARSE_TRIM)
185 line += strspn(line, delims + 1);
186
187 if (line[0] == '\0' || line[0] == delims[0])
188 goto again;
189
190 if (flags & PARSE_KEEP_COPY) {
191 free(parser->data);
192 parser->data = xstrdup(line);
193 }
194
195
196 t = 0;
197 do {
198
199 tokens[t] = line;
200
201
202 if ((t != (ntokens-1)) || !(flags & PARSE_GREEDY)) {
203
204 line += strcspn(line, delims[0] ? delims : delims + 1);
205 } else {
206
207 line = strchrnul(line, delims[0]);
208
209
210 if (flags & PARSE_TRIM) {
211 while (strchr(delims + 1, line[-1]) != NULL)
212 line--;
213 }
214 }
215
216
217 if (*line == delims[0])
218 *line = '\0';
219 else if (*line != '\0')
220 *line++ = '\0';
221
222#if 0
223 if (flags & PARSE_ESCAPE) {
224 strcpy_and_process_escape_sequences(tokens[t], tokens[t]);
225 }
226#endif
227
228 if (flags & PARSE_COLLAPSE)
229 line += strspn(line, delims + 1);
230
231 t++;
232 } while (*line && *line != delims[0] && t < ntokens);
233
234 if (t < mintokens) {
235 bb_error_msg("bad line %u: %d tokens found, %d needed",
236 parser->lineno, t, mintokens);
237 if (flags & PARSE_MIN_DIE)
238 xfunc_die();
239 goto again;
240 }
241
242 return t;
243}
244