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