symbol.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. /*
  2. * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
  3. * Released under the terms of the GNU GPL v2.0.
  4. */
  5. #include <ctype.h>
  6. #include <stdbool.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/utsname.h>
  10. #define LKC_DIRECT_LINK
  11. #include "lkc.h"
  12. extern int output_mode;
  13. struct symbol symbol_yes = {
  14. .name = "y",
  15. .curr = { "y", yes },
  16. .flags = SYMBOL_YES|SYMBOL_VALID,
  17. }, symbol_mod = {
  18. .name = "m",
  19. .curr = { "m", mod },
  20. .flags = SYMBOL_MOD|SYMBOL_VALID,
  21. }, symbol_no = {
  22. .name = "n",
  23. .curr = { "n", no },
  24. .flags = SYMBOL_NO|SYMBOL_VALID,
  25. }, symbol_empty = {
  26. .name = "",
  27. .curr = { "", no },
  28. .flags = SYMBOL_VALID,
  29. };
  30. int sym_change_count;
  31. struct symbol *modules_sym;
  32. tristate modules_val;
  33. void sym_add_default(struct symbol *sym, const char *def)
  34. {
  35. struct property *prop = prop_alloc(P_DEFAULT, sym);
  36. prop->expr = expr_alloc_symbol(sym_lookup(def, 1));
  37. }
  38. void sym_init(void)
  39. {
  40. struct symbol *sym;
  41. char *p;
  42. static bool inited = false;
  43. if (inited)
  44. return;
  45. inited = true;
  46. sym = sym_lookup("VERSION", 0);
  47. sym->type = S_STRING;
  48. sym->flags |= SYMBOL_AUTO;
  49. p = getenv("VERSION");
  50. if (p)
  51. sym_add_default(sym, p);
  52. sym = sym_lookup("TARGET_ARCH", 0);
  53. sym->type = S_STRING;
  54. sym->flags |= SYMBOL_AUTO;
  55. p = getenv("TARGET_ARCH");
  56. if (p)
  57. sym_add_default(sym, p);
  58. }
  59. enum symbol_type sym_get_type(struct symbol *sym)
  60. {
  61. enum symbol_type type = sym->type;
  62. if (type == S_TRISTATE) {
  63. if (sym_is_choice_value(sym) && sym->visible == yes)
  64. type = S_BOOLEAN;
  65. else if (modules_val == no)
  66. type = S_BOOLEAN;
  67. }
  68. return type;
  69. }
  70. const char *sym_type_name(enum symbol_type type)
  71. {
  72. switch (type) {
  73. case S_BOOLEAN:
  74. return "boolean";
  75. case S_TRISTATE:
  76. return "tristate";
  77. case S_INT:
  78. return "integer";
  79. case S_HEX:
  80. return "hex";
  81. case S_STRING:
  82. return "string";
  83. case S_UNKNOWN:
  84. return "unknown";
  85. case S_OTHER:
  86. break;
  87. }
  88. return "???";
  89. }
  90. struct property *sym_get_choice_prop(struct symbol *sym)
  91. {
  92. struct property *prop;
  93. for_all_choices(sym, prop)
  94. return prop;
  95. return NULL;
  96. }
  97. struct property *sym_get_default_prop(struct symbol *sym)
  98. {
  99. struct property *prop;
  100. for_all_defaults(sym, prop) {
  101. prop->visible.tri = expr_calc_value(prop->visible.expr);
  102. if (prop->visible.tri != no || output_mode)
  103. return prop;
  104. }
  105. return NULL;
  106. }
  107. struct property *sym_get_range_prop(struct symbol *sym)
  108. {
  109. struct property *prop;
  110. for_all_properties(sym, prop, P_RANGE) {
  111. prop->visible.tri = expr_calc_value(prop->visible.expr);
  112. if (prop->visible.tri != no)
  113. return prop;
  114. }
  115. return NULL;
  116. }
  117. static void sym_calc_visibility(struct symbol *sym)
  118. {
  119. struct property *prop;
  120. tristate tri;
  121. bool deselected = false;
  122. /* any prompt visible? */
  123. tri = no;
  124. for_all_prompts(sym, prop) {
  125. prop->visible.tri = expr_calc_value(prop->visible.expr);
  126. tri = E_OR(tri, prop->visible.tri);
  127. }
  128. if (tri == mod && (sym->type != S_TRISTATE || modules_val == no))
  129. tri = yes;
  130. if (sym->rev_dep_inv.expr && (expr_calc_value(sym->rev_dep_inv.expr) == yes)) {
  131. tri = no;
  132. deselected = true;
  133. }
  134. if (sym->visible != tri) {
  135. sym->visible = tri;
  136. sym_set_changed(sym);
  137. }
  138. if (sym_is_choice_value(sym) || deselected)
  139. return;
  140. tri = no;
  141. if (sym->rev_dep.expr)
  142. tri = expr_calc_value(sym->rev_dep.expr);
  143. if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
  144. tri = yes;
  145. if (sym->rev_dep.tri != tri) {
  146. sym->rev_dep.tri = tri;
  147. sym_set_changed(sym);
  148. }
  149. }
  150. static struct symbol *sym_calc_choice(struct symbol *sym)
  151. {
  152. struct symbol *def_sym;
  153. struct property *prop;
  154. struct expr *e;
  155. /* is the user choice visible? */
  156. def_sym = sym->user.val;
  157. if (def_sym) {
  158. sym_calc_visibility(def_sym);
  159. if (def_sym->visible != no)
  160. return def_sym;
  161. }
  162. /* any of the defaults visible? */
  163. for_all_defaults(sym, prop) {
  164. prop->visible.tri = expr_calc_value(prop->visible.expr);
  165. if (prop->visible.tri == no)
  166. continue;
  167. def_sym = prop_get_symbol(prop);
  168. sym_calc_visibility(def_sym);
  169. if (def_sym->visible != no)
  170. return def_sym;
  171. }
  172. /* just get the first visible value */
  173. prop = sym_get_choice_prop(sym);
  174. for (e = prop->expr; e; e = e->left.expr) {
  175. def_sym = e->right.sym;
  176. sym_calc_visibility(def_sym);
  177. if (def_sym->visible != no)
  178. return def_sym;
  179. }
  180. /* no choice? reset tristate value */
  181. sym->curr.tri = no;
  182. return NULL;
  183. }
  184. void sym_calc_value(struct symbol *sym)
  185. {
  186. struct symbol_value newval, oldval;
  187. struct property *prop;
  188. struct expr *e;
  189. if (!sym)
  190. return;
  191. if (sym->flags & SYMBOL_VALID)
  192. return;
  193. sym->flags |= SYMBOL_VALID;
  194. oldval = sym->curr;
  195. switch (sym->type) {
  196. case S_INT:
  197. case S_HEX:
  198. case S_STRING:
  199. newval = symbol_empty.curr;
  200. break;
  201. case S_BOOLEAN:
  202. case S_TRISTATE:
  203. newval = symbol_no.curr;
  204. break;
  205. default:
  206. sym->curr.val = sym->name;
  207. sym->curr.tri = no;
  208. return;
  209. }
  210. if (!sym_is_choice_value(sym))
  211. sym->flags &= ~SYMBOL_WRITE;
  212. sym_calc_visibility(sym);
  213. /* set default if recursively called */
  214. sym->curr = newval;
  215. switch (sym_get_type(sym)) {
  216. case S_BOOLEAN:
  217. case S_TRISTATE:
  218. if (sym_is_choice_value(sym) && sym->visible == yes) {
  219. prop = sym_get_choice_prop(sym);
  220. newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no;
  221. } else if (sym->rev_dep_inv.expr && (expr_calc_value(sym->rev_dep_inv.expr) == yes)) {
  222. newval.tri = no;
  223. } else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
  224. sym->flags |= SYMBOL_WRITE;
  225. if (sym_has_value(sym))
  226. newval.tri = sym->user.tri;
  227. else if (!sym_is_choice(sym)) {
  228. prop = sym_get_default_prop(sym);
  229. if (prop)
  230. newval.tri = expr_calc_value(prop->expr);
  231. }
  232. newval.tri = E_OR(E_AND(newval.tri, sym->visible), sym->rev_dep.tri);
  233. } else if (!sym_is_choice(sym)) {
  234. prop = sym_get_default_prop(sym);
  235. if (prop) {
  236. sym->flags |= SYMBOL_WRITE;
  237. newval.tri = expr_calc_value(prop->expr);
  238. }
  239. }
  240. if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
  241. newval.tri = yes;
  242. break;
  243. case S_STRING:
  244. case S_HEX:
  245. case S_INT:
  246. if (sym->visible != no) {
  247. sym->flags |= SYMBOL_WRITE;
  248. if (sym_has_value(sym)) {
  249. newval.val = sym->user.val;
  250. break;
  251. }
  252. }
  253. prop = sym_get_default_prop(sym);
  254. if (prop) {
  255. struct symbol *ds = prop_get_symbol(prop);
  256. if (ds) {
  257. sym->flags |= SYMBOL_WRITE;
  258. sym_calc_value(ds);
  259. newval.val = ds->curr.val;
  260. }
  261. }
  262. break;
  263. default:
  264. ;
  265. }
  266. sym->curr = newval;
  267. if (sym_is_choice(sym) && newval.tri == yes)
  268. sym->curr.val = sym_calc_choice(sym);
  269. if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
  270. sym_set_changed(sym);
  271. if (modules_sym == sym)
  272. modules_val = modules_sym->curr.tri;
  273. if (sym_is_choice(sym)) {
  274. int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
  275. prop = sym_get_choice_prop(sym);
  276. for (e = prop->expr; e; e = e->left.expr) {
  277. e->right.sym->flags |= flags;
  278. if (flags & SYMBOL_CHANGED)
  279. sym_set_changed(e->right.sym);
  280. }
  281. }
  282. }
  283. void sym_clear_all_valid(void)
  284. {
  285. struct symbol *sym;
  286. int i;
  287. for_all_symbols(i, sym)
  288. sym->flags &= ~SYMBOL_VALID;
  289. sym_change_count++;
  290. if (modules_sym)
  291. sym_calc_value(modules_sym);
  292. }
  293. void sym_set_changed(struct symbol *sym)
  294. {
  295. struct property *prop;
  296. sym->flags |= SYMBOL_CHANGED;
  297. for (prop = sym->prop; prop; prop = prop->next) {
  298. if (prop->menu)
  299. prop->menu->flags |= MENU_CHANGED;
  300. }
  301. }
  302. void sym_set_all_changed(void)
  303. {
  304. struct symbol *sym;
  305. int i;
  306. for_all_symbols(i, sym)
  307. sym_set_changed(sym);
  308. }
  309. bool sym_tristate_within_range(struct symbol *sym, tristate val)
  310. {
  311. int type = sym_get_type(sym);
  312. if (sym->visible == no)
  313. return false;
  314. if (type != S_BOOLEAN && type != S_TRISTATE)
  315. return false;
  316. if (type == S_BOOLEAN && val == mod)
  317. return false;
  318. if (sym->visible <= sym->rev_dep.tri)
  319. return false;
  320. if (sym_is_choice_value(sym) && sym->visible == yes)
  321. return val == yes;
  322. return val >= sym->rev_dep.tri && val <= sym->visible;
  323. }
  324. bool sym_set_tristate_value(struct symbol *sym, tristate val)
  325. {
  326. tristate oldval = sym_get_tristate_value(sym);
  327. if (oldval != val && !sym_tristate_within_range(sym, val))
  328. return false;
  329. if (sym->flags & SYMBOL_NEW) {
  330. sym->flags &= ~SYMBOL_NEW;
  331. sym_set_changed(sym);
  332. }
  333. if (sym_is_choice_value(sym) && val == yes) {
  334. struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
  335. cs->user.val = sym;
  336. cs->flags &= ~SYMBOL_NEW;
  337. }
  338. sym->user.tri = val;
  339. if (oldval != val) {
  340. sym_clear_all_valid();
  341. if (sym == modules_sym)
  342. sym_set_all_changed();
  343. }
  344. return true;
  345. }
  346. tristate sym_toggle_tristate_value(struct symbol *sym)
  347. {
  348. tristate oldval, newval;
  349. oldval = newval = sym_get_tristate_value(sym);
  350. do {
  351. switch (newval) {
  352. case no:
  353. newval = mod;
  354. break;
  355. case mod:
  356. newval = yes;
  357. break;
  358. case yes:
  359. newval = no;
  360. break;
  361. }
  362. if (sym_set_tristate_value(sym, newval))
  363. break;
  364. } while (oldval != newval);
  365. return newval;
  366. }
  367. bool sym_string_valid(struct symbol *sym, const char *str)
  368. {
  369. char ch;
  370. switch (sym->type) {
  371. case S_STRING:
  372. return true;
  373. case S_INT:
  374. ch = *str++;
  375. if (ch == '-')
  376. ch = *str++;
  377. if (!isdigit(ch))
  378. return false;
  379. if (ch == '0' && *str != 0)
  380. return false;
  381. while ((ch = *str++)) {
  382. if (!isdigit(ch))
  383. return false;
  384. }
  385. return true;
  386. case S_HEX:
  387. if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
  388. str += 2;
  389. ch = *str++;
  390. do {
  391. if (!isxdigit(ch))
  392. return false;
  393. } while ((ch = *str++));
  394. return true;
  395. case S_BOOLEAN:
  396. case S_TRISTATE:
  397. switch (str[0]) {
  398. case 'y': case 'Y':
  399. case 'm': case 'M':
  400. case 'n': case 'N':
  401. return true;
  402. }
  403. return false;
  404. default:
  405. return false;
  406. }
  407. }
  408. bool sym_string_within_range(struct symbol *sym, const char *str)
  409. {
  410. struct property *prop;
  411. int val;
  412. switch (sym->type) {
  413. case S_STRING:
  414. return sym_string_valid(sym, str);
  415. case S_INT:
  416. if (!sym_string_valid(sym, str))
  417. return false;
  418. prop = sym_get_range_prop(sym);
  419. if (!prop)
  420. return true;
  421. val = strtol(str, NULL, 10);
  422. return val >= strtol(prop->expr->left.sym->name, NULL, 10) &&
  423. val <= strtol(prop->expr->right.sym->name, NULL, 10);
  424. case S_HEX:
  425. if (!sym_string_valid(sym, str))
  426. return false;
  427. prop = sym_get_range_prop(sym);
  428. if (!prop)
  429. return true;
  430. val = strtol(str, NULL, 16);
  431. return val >= strtol(prop->expr->left.sym->name, NULL, 16) &&
  432. val <= strtol(prop->expr->right.sym->name, NULL, 16);
  433. case S_BOOLEAN:
  434. case S_TRISTATE:
  435. switch (str[0]) {
  436. case 'y': case 'Y':
  437. return sym_tristate_within_range(sym, yes);
  438. case 'm': case 'M':
  439. return sym_tristate_within_range(sym, mod);
  440. case 'n': case 'N':
  441. return sym_tristate_within_range(sym, no);
  442. }
  443. return false;
  444. default:
  445. return false;
  446. }
  447. }
  448. bool sym_set_string_value(struct symbol *sym, const char *newval)
  449. {
  450. const char *oldval;
  451. char *val;
  452. int size;
  453. switch (sym->type) {
  454. case S_BOOLEAN:
  455. case S_TRISTATE:
  456. switch (newval[0]) {
  457. case 'y': case 'Y':
  458. return sym_set_tristate_value(sym, yes);
  459. case 'm': case 'M':
  460. return sym_set_tristate_value(sym, mod);
  461. case 'n': case 'N':
  462. return sym_set_tristate_value(sym, no);
  463. }
  464. return false;
  465. default:
  466. ;
  467. }
  468. if (!sym_string_within_range(sym, newval))
  469. return false;
  470. if (sym->flags & SYMBOL_NEW) {
  471. sym->flags &= ~SYMBOL_NEW;
  472. sym_set_changed(sym);
  473. }
  474. oldval = sym->user.val;
  475. size = strlen(newval) + 1;
  476. if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
  477. size += 2;
  478. sym->user.val = val = malloc(size);
  479. *val++ = '0';
  480. *val++ = 'x';
  481. } else if (!oldval || strcmp(oldval, newval))
  482. sym->user.val = val = malloc(size);
  483. else
  484. return true;
  485. strcpy(val, newval);
  486. free((void *)oldval);
  487. sym_clear_all_valid();
  488. return true;
  489. }
  490. const char *sym_get_string_value(struct symbol *sym)
  491. {
  492. tristate val;
  493. switch (sym->type) {
  494. case S_BOOLEAN:
  495. case S_TRISTATE:
  496. val = sym_get_tristate_value(sym);
  497. switch (val) {
  498. case no:
  499. return "n";
  500. case mod:
  501. return "m";
  502. case yes:
  503. return "y";
  504. }
  505. break;
  506. default:
  507. ;
  508. }
  509. return (const char *)sym->curr.val;
  510. }
  511. bool sym_is_changable(struct symbol *sym)
  512. {
  513. return sym->visible > sym->rev_dep.tri;
  514. }
  515. struct symbol *sym_lookup(const char *name, int isconst)
  516. {
  517. struct symbol *symbol;
  518. const char *ptr;
  519. char *new_name;
  520. int hash = 0;
  521. if (name) {
  522. if (name[0] && !name[1]) {
  523. switch (name[0]) {
  524. case 'y': return &symbol_yes;
  525. case 'm': return &symbol_mod;
  526. case 'n': return &symbol_no;
  527. }
  528. }
  529. for (ptr = name; *ptr; ptr++)
  530. hash += *ptr;
  531. hash &= 0xff;
  532. for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
  533. if (!strcmp(symbol->name, name)) {
  534. if ((isconst && symbol->flags & SYMBOL_CONST) ||
  535. (!isconst && !(symbol->flags & SYMBOL_CONST)))
  536. return symbol;
  537. }
  538. }
  539. new_name = strdup(name);
  540. } else {
  541. new_name = NULL;
  542. hash = 256;
  543. }
  544. symbol = malloc(sizeof(*symbol));
  545. memset(symbol, 0, sizeof(*symbol));
  546. symbol->name = new_name;
  547. symbol->type = S_UNKNOWN;
  548. symbol->flags = SYMBOL_NEW;
  549. if (isconst)
  550. symbol->flags |= SYMBOL_CONST;
  551. symbol->next = symbol_hash[hash];
  552. symbol_hash[hash] = symbol;
  553. return symbol;
  554. }
  555. struct symbol *sym_find(const char *name)
  556. {
  557. struct symbol *symbol = NULL;
  558. const char *ptr;
  559. int hash = 0;
  560. if (!name)
  561. return NULL;
  562. if (name[0] && !name[1]) {
  563. switch (name[0]) {
  564. case 'y': return &symbol_yes;
  565. case 'm': return &symbol_mod;
  566. case 'n': return &symbol_no;
  567. }
  568. }
  569. for (ptr = name; *ptr; ptr++)
  570. hash += *ptr;
  571. hash &= 0xff;
  572. for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) {
  573. if (!strcmp(symbol->name, name) &&
  574. !(symbol->flags & SYMBOL_CONST))
  575. break;
  576. }
  577. return symbol;
  578. }
  579. struct symbol *sym_check_deps(struct symbol *sym);
  580. static struct symbol *sym_check_expr_deps(struct expr *e)
  581. {
  582. struct symbol *sym;
  583. if (!e)
  584. return NULL;
  585. switch (e->type) {
  586. case E_OR:
  587. case E_AND:
  588. sym = sym_check_expr_deps(e->left.expr);
  589. if (sym)
  590. return sym;
  591. return sym_check_expr_deps(e->right.expr);
  592. case E_NOT:
  593. return sym_check_expr_deps(e->left.expr);
  594. case E_EQUAL:
  595. case E_UNEQUAL:
  596. sym = sym_check_deps(e->left.sym);
  597. if (sym)
  598. return sym;
  599. return sym_check_deps(e->right.sym);
  600. case E_SYMBOL:
  601. return sym_check_deps(e->left.sym);
  602. default:
  603. break;
  604. }
  605. printf("Oops! How to check %d?\n", e->type);
  606. return NULL;
  607. }
  608. struct symbol *sym_check_deps(struct symbol *sym)
  609. {
  610. struct symbol *sym2;
  611. struct property *prop;
  612. if (sym->flags & SYMBOL_CHECK_DONE)
  613. return NULL;
  614. if (sym->flags & SYMBOL_CHECK) {
  615. printf("Warning! Found recursive dependency: %s", sym->name);
  616. return sym;
  617. }
  618. sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED);
  619. sym2 = sym_check_expr_deps(sym->rev_dep.expr);
  620. if (sym2)
  621. goto out;
  622. for (prop = sym->prop; prop; prop = prop->next) {
  623. if (prop->type == P_CHOICE || prop->type == P_SELECT || prop->type == P_SELECTNOT)
  624. continue;
  625. sym2 = sym_check_expr_deps(prop->visible.expr);
  626. if (sym2)
  627. goto out;
  628. if (prop->type != P_DEFAULT || sym_is_choice(sym))
  629. continue;
  630. sym2 = sym_check_expr_deps(prop->expr);
  631. if (sym2)
  632. goto out;
  633. }
  634. out:
  635. if (sym2)
  636. printf(" %s", sym->name);
  637. sym->flags &= ~SYMBOL_CHECK;
  638. return sym2;
  639. }
  640. struct property *prop_alloc(enum prop_type type, struct symbol *sym)
  641. {
  642. struct property *prop;
  643. struct property **propp;
  644. prop = malloc(sizeof(*prop));
  645. memset(prop, 0, sizeof(*prop));
  646. prop->type = type;
  647. prop->sym = sym;
  648. prop->file = current_file;
  649. prop->lineno = zconf_lineno();
  650. /* append property to the prop list of symbol */
  651. if (sym) {
  652. for (propp = &sym->prop; *propp; propp = &(*propp)->next)
  653. ;
  654. *propp = prop;
  655. }
  656. return prop;
  657. }
  658. struct symbol *prop_get_symbol(struct property *prop)
  659. {
  660. if (prop->expr && (prop->expr->type == E_SYMBOL ||
  661. prop->expr->type == E_CHOICE))
  662. return prop->expr->left.sym;
  663. return NULL;
  664. }
  665. const char *prop_get_type_name(enum prop_type type)
  666. {
  667. switch (type) {
  668. case P_PROMPT:
  669. return "prompt";
  670. case P_COMMENT:
  671. return "comment";
  672. case P_MENU:
  673. return "menu";
  674. case P_DEFAULT:
  675. return "default";
  676. case P_CHOICE:
  677. return "choice";
  678. case P_SELECT:
  679. case P_SELECTNOT:
  680. return "select";
  681. case P_RANGE:
  682. return "range";
  683. case P_UNKNOWN:
  684. break;
  685. }
  686. return "unknown";
  687. }