cmdline: add the incomplete token string as an argument of iter_start()
[libcmdline.git] / src / lib / cmdline_parse_string.c
1 /*-
2  * Copyright (c) <2010>, Intel Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * - Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * - Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  *
17  * - Neither the name of Intel Corporation nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
32  * OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 /*
36  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
37  * All rights reserved.
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions are met:
40  *
41  *     * Redistributions of source code must retain the above copyright
42  *       notice, this list of conditions and the following disclaimer.
43  *     * Redistributions in binary form must reproduce the above copyright
44  *       notice, this list of conditions and the following disclaimer in the
45  *       documentation and/or other materials provided with the distribution.
46  *     * Neither the name of the University of California, Berkeley nor the
47  *       names of its contributors may be used to endorse or promote products
48  *       derived from this software without specific prior written permission.
49  *
50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
51  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
52  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
53  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
54  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
55  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
57  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
59  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60  */
61
62 #include <stdio.h>
63 #include <inttypes.h>
64 #include <ctype.h>
65 #include <string.h>
66
67 #include "cmdline_parse.h"
68 #include "cmdline_parse_string.h"
69
70 #define MULTISTRING_HELP "Mul-choice STRING"
71 #define ANYSTRING_HELP   "Any STRING"
72 #define FIXEDSTRING_HELP "Fixed STRING"
73
74 static unsigned int
75 get_token_len(const char *s)
76 {
77         char c;
78         unsigned int i=0;
79
80         c = s[i];
81         while (c!='#' && c!='\0') {
82                 i++;
83                 c = s[i];
84         }
85         return i;
86 }
87
88 static const char *
89 get_next_token(const char *s)
90 {
91         unsigned int i;
92         i = get_token_len(s);
93         if (s[i] == '#')
94                 return s+i+1;
95         return NULL;
96 }
97
98 static int
99 parse_fixed_string(struct cmdline_token_string_data *sd,
100                    const char *buf, unsigned token_len)
101 {
102         unsigned int conf_token_len;
103         const char *str;
104
105         str = sd->str;
106         for (str = sd->str; str != NULL ; str = get_next_token(str)) {
107
108                 conf_token_len = get_token_len(str);
109
110                 /* if token from config is too big... */
111                 if (conf_token_len >= STR_TOKEN_SIZE - 1)
112                         continue;
113
114                 /* compare conf token and user token */
115                 if (token_len == conf_token_len &&
116                     strncmp(buf, str, token_len) == 0)
117                         return 0;
118         }
119
120         return -1;
121 }
122
123 static int
124 cmdline_parse_string(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
125                      unsigned ressize)
126 {
127         struct cmdline_token_string *tk2 = (struct cmdline_token_string *)tk;
128         struct cmdline_token_string_data *sd = &tk2->string_data;;
129         unsigned int token_len;
130
131         if (res && ressize < STR_TOKEN_SIZE)
132                 return -1;
133
134         token_len = strlen(buf);
135
136         if (token_len >= (STR_TOKEN_SIZE - 1) || token_len == 0)
137                 return -1;
138
139         /* fixed string */
140         if (sd->str) {
141                 if (parse_fixed_string(sd, buf, token_len) < 0)
142                         return -1;
143         }
144
145         /* we already checked that token_len is < STR_TOKEN_SIZE-1 */
146         if (res)
147                 strcpy(res, buf);
148
149         return token_len;
150 }
151
152 static int
153 cmdline_complete_string_start(cmdline_parse_token_hdr_t *tk,
154                               __attribute__((unused)) const char *tokstr,
155                               void **opaque)
156 {
157         struct cmdline_token_string *tk2 = (struct cmdline_token_string *)tk;
158         struct cmdline_token_string_data *sd = &tk2->string_data;;
159         const char *str;
160
161         str = sd->str;
162         *opaque = (void *)str;
163         if (str == NULL)
164                 return -1; /* no completion */
165         return 0;
166 }
167
168 static int
169 cmdline_complete_string_iterate(cmdline_parse_token_hdr_t *tk, void **opaque,
170                                 char *dstbuf, unsigned int size)
171 {
172         const char *s;
173         unsigned int len;
174
175         s = *opaque;
176         if (s == NULL)
177                 return -1;
178         *opaque = (void *)get_next_token(s);
179
180         len = get_token_len(s);
181         if (len > size - 1)
182                 return -1;
183
184         memcpy(dstbuf, s, len);
185         dstbuf[len] = '\0';
186         return 0;
187 }
188
189 static int
190 cmdline_help_string(cmdline_parse_token_hdr_t *tk, char *dstbuf,
191                     unsigned int size)
192 {
193         struct cmdline_token_string *tk2 = (struct cmdline_token_string *)tk;
194         struct cmdline_token_string_data *sd = &tk2->string_data;;
195         const char *s;
196
197         s = sd->str;
198
199         if (s != NULL) {
200                 if (get_next_token(s))
201                         strncpy(dstbuf, MULTISTRING_HELP, size);
202                 else
203                         strncpy(dstbuf, FIXEDSTRING_HELP, size);
204         }
205         else {
206                 strncpy(dstbuf, ANYSTRING_HELP, size);
207         }
208
209         dstbuf[size-1] = '\0';
210
211         return 0;
212 }
213
214 struct cmdline_token_ops cmdline_token_string_ops = {
215         .parse = cmdline_parse_string,
216         .complete_start = cmdline_complete_string_start,
217         .complete_iterate = cmdline_complete_string_iterate,
218         .complete_end = NULL,
219         .help = cmdline_help_string,
220 };