aboutsummaryrefslogtreecommitdiff
path: root/libbb/parse_config.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-07-19 09:27:19 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-07-19 09:27:19 +0000
commit2e157ddf9ecd9d58864425f0e87409ddc218df94 (patch)
tree18f415d4847897a12d790b545f94c32ae68c199c /libbb/parse_config.c
parentbd28f6bf7f53ede8df39112d40cb52f2a3d00177 (diff)
downloadbusybox-w32-2e157ddf9ecd9d58864425f0e87409ddc218df94.tar.gz
busybox-w32-2e157ddf9ecd9d58864425f0e87409ddc218df94.tar.bz2
busybox-w32-2e157ddf9ecd9d58864425f0e87409ddc218df94.zip
libbb: updated config_parse() from Vladimir
function old new delta config_read 385 460 +75 runsvdir_main 1701 1716 +15 readit 331 338 +7 passwd_main 1049 1053 +4 parse_command 1504 1507 +3 decode_format_string 822 824 +2 bb__parsespent 117 119 +2 udhcp_get_option 221 222 +1 changepath 196 194 -2 parse_inittab 400 396 -4 nameif_main 683 679 -4 make_device 1176 1172 -4 config_open 48 40 -8 expand_main 698 689 -9 readcmd 1012 1002 -10 config_free_data 37 21 -16 SynchronizeFile 683 643 -40 sleep_main 474 362 -112 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 8/10 up/down: 109/-209) Total: -100 bytes
Diffstat (limited to 'libbb/parse_config.c')
-rw-r--r--libbb/parse_config.c148
1 files changed, 107 insertions, 41 deletions
diff --git a/libbb/parse_config.c b/libbb/parse_config.c
index 5f6dbbde1..3945501ad 100644
--- a/libbb/parse_config.c
+++ b/libbb/parse_config.c
@@ -9,23 +9,51 @@
9 9
10#include "libbb.h" 10#include "libbb.h"
11 11
12#if ENABLE_PARSE
13int parse_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
14int parse_main(int argc UNUSED_PARAM, char **argv)
15{
16 const char *delims = "# \t";
17 unsigned flags = 0;
18 int mintokens = 0, ntokens = 128;
19 opt_complementary = "-1:n+:m+:f+";
20 getopt32(argv, "n:m:d:f:", &ntokens, &mintokens, &delims, &flags);
21 //argc -= optind;
22 argv += optind;
23 while (*argv) {
24 parser_t *p = config_open(*argv);
25 if (p) {
26 int n;
27 char **t = xmalloc(sizeof(char *) * ntokens);
28 while ((n = config_read(p, t, ntokens, mintokens, delims, flags)) > 0) {
29 for (int i = 0; i < n; ++i)
30 printf("[%s]", t[i]);
31 puts("");
32 }
33 config_close(p);
34 }
35 argv++;
36 }
37 return EXIT_SUCCESS;
38}
39#endif
40
12/* 41/*
13 42
14Typical usage: 43Typical usage:
15 44
16----- CUT ----- 45----- CUT -----
17 char *t[3]; // tokens placeholder 46 char *t[3]; // tokens placeholder
18 parser_t p; // parser structure 47 parser_t *p = config_open(filename);
19 // open file 48 if (p) {
20 if (config_open(filename, &p)) {
21 // parse line-by-line 49 // parse line-by-line
22 while (*config_read(&p, t, 3, 0, delimiters, comment_char) >= 0) { // 0..3 tokens 50 while (config_read(p, t, 3, 0, delimiters, flags)) { // 1..3 tokens
23 // use tokens 51 // use tokens
24 bb_error_msg("TOKENS: [%s][%s][%s]", t[0], t[1], t[2]); 52 bb_error_msg("TOKENS: [%s][%s][%s]", t[0], t[1], t[2]);
25 } 53 }
26 ... 54 ...
27 // free parser 55 // free parser
28 config_close(&p); 56 config_close(p);
29 } 57 }
30----- CUT ----- 58----- CUT -----
31 59
@@ -35,44 +63,69 @@ parser_t* FAST_FUNC config_open(const char *filename)
35{ 63{
36 parser_t *parser = xzalloc(sizeof(parser_t)); 64 parser_t *parser = xzalloc(sizeof(parser_t));
37 /* empty file configures nothing */ 65 /* empty file configures nothing */
38 parser->fp = fopen_or_warn(filename, "r"); 66 parser->fp = fopen_or_warn_stdin(filename);
39 if (parser->fp) 67 if (parser->fp)
40 return parser; 68 return parser;
41 config_close (parser);
42 if (ENABLE_FEATURE_CLEAN_UP) 69 if (ENABLE_FEATURE_CLEAN_UP)
43 free(parser); 70 free(parser);
44 return NULL; 71 return NULL;
45} 72}
46 73
47static void config_free_data(parser_t *const parser) 74static void config_free_data(parser_t *const parser)
48{ 75{
49 free(parser->line); 76 free(parser->line);
50 free(parser->data); 77 parser->line = NULL;
51 parser->line = parser->data = NULL; 78 USE_FEATURE_PARSE_COPY(
79 free(parser->data);
80 parser->data = NULL;
81 )
52} 82}
83
53void FAST_FUNC config_close(parser_t *parser) 84void FAST_FUNC config_close(parser_t *parser)
54{ 85{
55 config_free_data(parser); 86 config_free_data(parser);
56 fclose(parser->fp); 87 fclose(parser->fp);
57} 88}
58 89
59int FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mintokens, const char *delims, char comment) 90/*
911. Read a line from config file. If nothing to read then bail out returning 0.
92 Handle continuation character. Advance lineno for each physical line. Cut comments.
932. if PARSE_DONT_TRIM is not set (default) skip leading and cut trailing delimiters, if any.
943. If resulting line is empty goto 1.
954. Look for first delimiter. If PARSE_DONT_REDUCE or PARSE_DONT_TRIM is set then pin empty token.
965. Else (default) if number of seen tokens is equal to max number of tokens (token is the last one)
97 and PARSE_LAST_IS_GREEDY is set then pin the remainder of the line as the last token.
98 Else (token is not last or PARSE_LAST_IS_GREEDY is not set) just replace first delimiter with '\0'
99 thus delimiting token and pin it.
1006. Advance line pointer past the end of token. If number of seen tokens is less than required number
101 of tokens then goto 4.
1027. Control the number of seen tokens is not less the min number of tokens. Die if condition is not met.
1038. Return the number of seen tokens.
104
105mintokens > 0 make config_read() exit with error message if less than mintokens
106(but more than 0) are found. Empty lines are always skipped (not warned about).
107*/
108#undef config_read
109int FAST_FUNC config_read(parser_t *parser, char **tokens, unsigned flags, const char *delims)
60{ 110{
61 char *line, *q; 111 char *line, *q;
62 int ii, seen; 112 char comment = *delims++;
63 /* do not treat consecutive delimiters as one delimiter */ 113 int ii;
64 bool noreduce = (ntokens < 0); 114 int ntokens = flags & 0xFF;
65 if (noreduce) 115 int mintokens = (flags & 0xFF00) >> 8;
66 ntokens = -ntokens; 116
67 117 /*
68 memset(tokens, 0, sizeof(tokens[0]) * ntokens); 118 // N.B. this could only be used in read-in-one-go version, or when tokens use xstrdup(). TODO
119 if (!parser->lineno || !(flags & PARSE_DONT_NULL))
120 */
121 memset(tokens, 0, sizeof(tokens[0]) * ntokens);
69 config_free_data(parser); 122 config_free_data(parser);
70 123
71 while (1) { 124 while (1) {
72//TODO: speed up xmalloc_fgetline by internally using fgets, not fgetc 125//TODO: speed up xmalloc_fgetline by internally using fgets, not fgetc
73 line = xmalloc_fgetline(parser->fp); 126 line = xmalloc_fgetline(parser->fp);
74 if (!line) 127 if (!line)
75 return -1; 128 return 0;
76 129
77 parser->lineno++; 130 parser->lineno++;
78 // handle continuations. Tito's code stolen :) 131 // handle continuations. Tito's code stolen :)
@@ -98,12 +151,22 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mint
98 *q = '\0'; 151 *q = '\0';
99 ii = q - line; 152 ii = q - line;
100 } 153 }
101 // skip leading delimiters 154 // skip leading and trailing delimiters
102 seen = strspn(line, delims); 155 if (!(flags & PARSE_DONT_TRIM)) {
103 if (seen) { 156 // skip leading
104 ii -= seen; 157 int n = strspn(line, delims);
105 strcpy(line, line + seen); 158 if (n) {
159 ii -= n;
160 strcpy(line, line + n);
161 }
162 // cut trailing
163 if (ii) {
164 while (strchr(delims, line[--ii]))
165 continue;
166 line[++ii] = '\0';
167 }
106 } 168 }
169 // if something still remains -> return it
107 if (ii) 170 if (ii)
108 break; 171 break;
109 172
@@ -112,36 +175,39 @@ int FAST_FUNC config_read(parser_t *parser, char **tokens, int ntokens, int mint
112 free(line); 175 free(line);
113 } 176 }
114 177
115 // non-empty line found, parse and return 178 // non-empty line found, parse and return the number of tokens
116 179
117 // store line 180 // store line
118 parser->line = line = xrealloc(line, ii + 1); 181 parser->line = line = xrealloc(line, ii + 1);
119 parser->data = xstrdup(line); 182 USE_FEATURE_PARSE_COPY(
183 parser->data = xstrdup(line);
184 )
120 185
121 /* now split line to tokens */ 186 /* now split line to tokens */
122 ii = noreduce ? seen : 0;
123 ntokens--; // now it's max allowed token no 187 ntokens--; // now it's max allowed token no
124 while (1) { 188 // N.B, non-empty remainder is also a token,
189 // so if ntokens <= 1, we just return the whole line
190 // N.B. if PARSE_LAST_IS_GREEDY is set the remainder of the line is stuck to the last token
191 for (ii = 0; *line && ii <= ntokens; ) {
192 //bb_info_msg("L[%s]", line);
125 // get next token 193 // get next token
126 if (ii == ntokens) 194 // at the last token and need greedy token ->
127 break; 195 if ((flags & PARSE_LAST_IS_GREEDY) && (ii == ntokens)) {
128 q = line + strcspn(line, delims); 196 // ... don't cut the line
129 if (!*q) 197 q = line + strlen(line);
130 break; 198 } else {
199 // vanilla token. cut the line at the first delim
200 q = line + strcspn(line, delims);
201 *q++ = '\0';
202 }
131 // pin token 203 // pin token
132 *q++ = '\0'; 204 if ((flags & (PARSE_DONT_REDUCE|PARSE_DONT_TRIM)) || *line) {
133 if (noreduce || *line) { 205 //bb_info_msg("N[%d] T[%s]", ii, line);
134 tokens[ii++] = line; 206 tokens[ii++] = line;
135//bb_info_msg("L[%d] T[%s]\n", ii, line);
136 } 207 }
137 line = q; 208 line = q;
138 } 209 }
139 210
140 // non-empty remainder is also a token,
141 // so if ntokens <= 1, we just return the whole line
142 if (noreduce || *line)
143 tokens[ii++] = line;
144
145 if (ii < mintokens) 211 if (ii < mintokens)
146 bb_error_msg_and_die("bad line %u: %d tokens found, %d needed", 212 bb_error_msg_and_die("bad line %u: %d tokens found, %d needed",
147 parser->lineno, ii, mintokens); 213 parser->lineno, ii, mintokens);