kconfig: support user-defined function and recursively expanded variable · torvalds/linux@9ced3bd (original) (raw)
`@@ -177,6 +177,72 @@ static char *function_expand(const char *name, int argc, char *argv[])
`
177
177
`return NULL;
`
178
178
`}
`
179
179
``
``
180
`+
/*
`
``
181
`+
- Variables (and user-defined functions)
`
``
182
`+
*/
`
``
183
`+
static LIST_HEAD(variable_list);
`
``
184
+
``
185
`+
struct variable {
`
``
186
`+
char *name;
`
``
187
`+
char *value;
`
``
188
`+
struct list_head node;
`
``
189
`+
};
`
``
190
+
``
191
`+
static struct variable *variable_lookup(const char *name)
`
``
192
`+
{
`
``
193
`+
struct variable *v;
`
``
194
+
``
195
`+
list_for_each_entry(v, &variable_list, node) {
`
``
196
`+
if (!strcmp(name, v->name))
`
``
197
`+
return v;
`
``
198
`+
}
`
``
199
+
``
200
`+
return NULL;
`
``
201
`+
}
`
``
202
+
``
203
`+
static char *variable_expand(const char *name, int argc, char *argv[])
`
``
204
`+
{
`
``
205
`+
struct variable *v;
`
``
206
+
``
207
`+
v = variable_lookup(name);
`
``
208
`+
if (!v)
`
``
209
`+
return NULL;
`
``
210
+
``
211
`+
return expand_string_with_args(v->value, argc, argv);
`
``
212
`+
}
`
``
213
+
``
214
`+
void variable_add(const char *name, const char *value)
`
``
215
`+
{
`
``
216
`+
struct variable *v;
`
``
217
+
``
218
`+
v = variable_lookup(name);
`
``
219
`+
if (v) {
`
``
220
`+
free(v->value);
`
``
221
`+
} else {
`
``
222
`+
v = xmalloc(sizeof(*v));
`
``
223
`+
v->name = xstrdup(name);
`
``
224
`+
list_add_tail(&v->node, &variable_list);
`
``
225
`+
}
`
``
226
+
``
227
`+
v->value = xstrdup(value);
`
``
228
`+
}
`
``
229
+
``
230
`+
static void variable_del(struct variable *v)
`
``
231
`+
{
`
``
232
`+
list_del(&v->node);
`
``
233
`+
free(v->name);
`
``
234
`+
free(v->value);
`
``
235
`+
free(v);
`
``
236
`+
}
`
``
237
+
``
238
`+
void variable_all_del(void)
`
``
239
`+
{
`
``
240
`+
struct variable *v, *tmp;
`
``
241
+
``
242
`+
list_for_each_entry_safe(v, tmp, &variable_list, node)
`
``
243
`+
variable_del(v);
`
``
244
`+
}
`
``
245
+
180
246
`/*
`
181
247
` * Evaluate a clause with arguments. argc/argv are arguments from the upper
`
182
248
` * function call.
`
`@@ -185,14 +251,26 @@ static char *function_expand(const char *name, int argc, char *argv[])
`
185
251
` */
`
186
252
`static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
`
187
253
`{
`
188
``
`-
char *tmp, *name, *res, *prev, *p;
`
``
254
`+
char *tmp, *name, *res, *endptr, *prev, *p;
`
189
255
`int new_argc = 0;
`
190
256
`char *new_argv[FUNCTION_MAX_ARGS];
`
191
257
`int nest = 0;
`
192
258
`int i;
`
``
259
`+
unsigned long n;
`
193
260
``
194
261
`tmp = xstrndup(str, len);
`
195
262
``
``
263
`+
/*
`
``
264
`+
- If variable name is '1', '2', etc. It is generally an argument
`
``
265
`+
- from a user-function call (i.e. local-scope variable). If not
`
``
266
`+
- available, then look-up global-scope variables.
`
``
267
`+
*/
`
``
268
`+
n = strtoul(tmp, &endptr, 10);
`
``
269
`+
if (!*endptr && n > 0 && n <= argc) {
`
``
270
`+
res = xstrdup(argv[n - 1]);
`
``
271
`+
goto free_tmp;
`
``
272
`+
}
`
``
273
+
196
274
`prev = p = tmp;
`
197
275
``
198
276
`/*
`
`@@ -238,6 +316,11 @@ static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
`
238
316
`new_argv[i] = expand_string_with_args(new_argv[i + 1],
`
239
317
`argc, argv);
`
240
318
``
``
319
`+
/* Search for variables */
`
``
320
`+
res = variable_expand(name, new_argc, new_argv);
`
``
321
`+
if (res)
`
``
322
`+
goto free;
`
``
323
+
241
324
`/* Look for built-in functions */
`
242
325
`res = function_expand(name, new_argc, new_argv);
`
243
326
`if (res)
`
`@@ -255,6 +338,7 @@ static char *eval_clause(const char *str, size_t len, int argc, char *argv[])
`
255
338
`for (i = 0; i < new_argc; i++)
`
256
339
`free(new_argv[i]);
`
257
340
`free(name);
`
``
341
`+
free_tmp:
`
258
342
`free(tmp);
`
259
343
``
260
344
`return res;
`