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

`+

`

``

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

`+

`

``

265

`+

`

``

266

`+

`

``

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;

`