pline.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. /** @file pline.c
  2. */
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <assert.h>
  8. #include <faux/faux.h>
  9. #include <faux/str.h>
  10. #include <faux/list.h>
  11. #include <faux/argv.h>
  12. #include <sysrepo.h>
  13. #include <sysrepo/xpath.h>
  14. #include <sysrepo/values.h>
  15. #include <libyang/tree_edit.h>
  16. #include "sr_copypaste.h"
  17. #include "pline.h"
  18. #define NODETYPE_CONF (LYS_CONTAINER | LYS_LIST | LYS_LEAF | LYS_LEAFLIST)
  19. static pexpr_t *pexpr_new(void)
  20. {
  21. pexpr_t *pexpr = NULL;
  22. pexpr = faux_zmalloc(sizeof(*pexpr));
  23. assert(pexpr);
  24. if (!pexpr)
  25. return NULL;
  26. // Initialize
  27. pexpr->xpath = NULL;
  28. pexpr->value = NULL;
  29. pexpr->active = BOOL_FALSE;
  30. pexpr->pat = PAT_NONE;
  31. pexpr->args_num = 0;
  32. pexpr->list_pos = 0;
  33. return pexpr;
  34. }
  35. static void pexpr_free(pexpr_t *pexpr)
  36. {
  37. if (!pexpr)
  38. return;
  39. faux_str_free(pexpr->xpath);
  40. faux_str_free(pexpr->value);
  41. free(pexpr);
  42. }
  43. static pcompl_t *pcompl_new(void)
  44. {
  45. pcompl_t *pcompl = NULL;
  46. pcompl = faux_zmalloc(sizeof(*pcompl));
  47. assert(pcompl);
  48. if (!pcompl)
  49. return NULL;
  50. // Initialize
  51. pcompl->type = PCOMPL_NODE;
  52. pcompl->node = NULL;
  53. pcompl->xpath = NULL;
  54. return pcompl;
  55. }
  56. static void pcompl_free(pcompl_t *pcompl)
  57. {
  58. if (!pcompl)
  59. return;
  60. faux_str_free(pcompl->xpath);
  61. free(pcompl);
  62. }
  63. pline_t *pline_new(sr_session_ctx_t *sess)
  64. {
  65. pline_t *pline = NULL;
  66. pline = faux_zmalloc(sizeof(*pline));
  67. assert(pline);
  68. if (!pline)
  69. return NULL;
  70. // Init
  71. pline->sess = sess;
  72. pline->invalid = BOOL_FALSE;
  73. pline->exprs = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
  74. NULL, NULL, (faux_list_free_fn)pexpr_free);
  75. pline->compls = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
  76. NULL, NULL, (faux_list_free_fn)pcompl_free);
  77. return pline;
  78. }
  79. void pline_free(pline_t *pline)
  80. {
  81. if (!pline)
  82. return;
  83. faux_list_free(pline->exprs);
  84. faux_list_free(pline->compls);
  85. faux_free(pline);
  86. }
  87. static pexpr_t *pline_add_expr(pline_t *pline, const char *xpath)
  88. {
  89. pexpr_t *pexpr = NULL;
  90. assert(pline);
  91. pexpr = pexpr_new();
  92. if (xpath)
  93. pexpr->xpath = faux_str_dup(xpath);
  94. faux_list_add(pline->exprs, pexpr);
  95. return pexpr;
  96. }
  97. pexpr_t *pline_current_expr(pline_t *pline)
  98. {
  99. assert(pline);
  100. if (faux_list_len(pline->exprs) == 0)
  101. pline_add_expr(pline, NULL);
  102. return (pexpr_t *)faux_list_data(faux_list_tail(pline->exprs));
  103. }
  104. static void pline_add_compl(pline_t *pline,
  105. pcompl_type_e type, const struct lysc_node *node, char *xpath)
  106. {
  107. pcompl_t *pcompl = NULL;
  108. assert(pline);
  109. pcompl = pcompl_new();
  110. pcompl->type = type;
  111. pcompl->node = node;
  112. if (xpath)
  113. pcompl->xpath = faux_str_dup(xpath);
  114. faux_list_add(pline->compls, pcompl);
  115. }
  116. static void pline_add_compl_subtree(pline_t *pline, const struct lys_module *module,
  117. const struct lysc_node *node)
  118. {
  119. const struct lysc_node *subtree = NULL;
  120. const struct lysc_node *iter = NULL;
  121. assert(pline);
  122. assert(module);
  123. if (node)
  124. subtree = lysc_node_child(node);
  125. else
  126. subtree = module->compiled->data;
  127. LY_LIST_FOR(subtree, iter) {
  128. if (!(iter->nodetype & NODETYPE_CONF))
  129. continue;
  130. if (!(iter->flags & LYS_CONFIG_W))
  131. continue;
  132. pline_add_compl(pline, PCOMPL_NODE, iter, NULL);
  133. }
  134. }
  135. void pline_debug(pline_t *pline)
  136. {
  137. faux_list_node_t *iter = NULL;
  138. pexpr_t *pexpr = NULL;
  139. pcompl_t *pcompl = NULL;
  140. printf("====== Pline:\n\n");
  141. printf("invalid = %s\n", pline->invalid ? "true" : "false");
  142. printf("\n");
  143. printf("=== Expressions:\n\n");
  144. iter = faux_list_head(pline->exprs);
  145. while ((pexpr = (pexpr_t *)faux_list_each(&iter))) {
  146. char *pat = NULL;
  147. printf("pexpr.xpath = %s\n", pexpr->xpath ? pexpr->xpath : "NULL");
  148. printf("pexpr.value = %s\n", pexpr->value ? pexpr->value : "NULL");
  149. printf("pexpr.active = %s\n", pexpr->active ? "true" : "false");
  150. switch (pexpr->pat) {
  151. case 0x0001:
  152. pat = "NONE";
  153. break;
  154. case 0x0002:
  155. pat = "CONTAINER";
  156. break;
  157. case 0x0004:
  158. pat = "LIST";
  159. break;
  160. case 0x0008:
  161. pat = "LIST_KEY";
  162. break;
  163. case 0x0010:
  164. pat = "LIST_KEY_INCOMPLETED";
  165. break;
  166. case 0x0020:
  167. pat = "LEAF";
  168. break;
  169. case 0x0040:
  170. pat = "LEAF_VALUE";
  171. break;
  172. case 0x0080:
  173. pat = "LEAF_EMPTY";
  174. break;
  175. case 0x0100:
  176. pat = "LEAFLIST";
  177. break;
  178. case 0x0200:
  179. pat = "LEAFLIST_VALUE";
  180. break;
  181. default:
  182. pat = "UNKNOWN";
  183. break;
  184. }
  185. printf("pexpr.pat = %s\n", pat);
  186. printf("pexpr.args_num = %lu\n", pexpr->args_num);
  187. printf("pexpr.list_pos = %lu\n", pexpr->list_pos);
  188. printf("\n");
  189. }
  190. printf("=== Completions:\n\n");
  191. iter = faux_list_head(pline->compls);
  192. while ((pcompl = (pcompl_t *)faux_list_each(&iter))) {
  193. printf("pcompl.type = %s\n", (pcompl->type == PCOMPL_NODE) ?
  194. "PCOMPL_NODE" : "PCOMPL_TYPE");
  195. printf("pcompl.node = %s\n", pcompl->node ? pcompl->node->name : "NULL");
  196. printf("pcompl.xpath = %s\n", pcompl->xpath ? pcompl->xpath : "NULL");
  197. printf("\n");
  198. }
  199. }
  200. // Don't use standard lys_find_child() because it checks given module to be
  201. // equal to found node's module. So augmented nodes will not be found.
  202. static const struct lysc_node *find_child(const struct lysc_node *node,
  203. const char *name)
  204. {
  205. const struct lysc_node *iter = NULL;
  206. if (!node)
  207. return NULL;
  208. LY_LIST_FOR(node, iter) {
  209. if (!(iter->nodetype & NODETYPE_CONF))
  210. continue;
  211. if (!(iter->flags & LYS_CONFIG_W))
  212. continue;
  213. if (!faux_str_cmp(iter->name, name))
  214. return iter;
  215. }
  216. return NULL;
  217. }
  218. static struct lysc_ident *find_ident(struct lysc_ident *ident, const char *name)
  219. {
  220. LY_ARRAY_COUNT_TYPE u = 0;
  221. if (!ident)
  222. return NULL;
  223. if (!ident->derived) {
  224. if (!faux_str_cmp(name, ident->name))
  225. return ident;
  226. return NULL;
  227. }
  228. LY_ARRAY_FOR(ident->derived, u) {
  229. struct lysc_ident *identity = find_ident(ident->derived[u], name);
  230. if (identity)
  231. return identity;
  232. }
  233. return NULL;
  234. }
  235. static const char *identityref_prefix(struct lysc_type_identityref *type,
  236. const char *name)
  237. {
  238. LY_ARRAY_COUNT_TYPE u = 0;
  239. assert(type);
  240. LY_ARRAY_FOR(type->bases, u) {
  241. struct lysc_ident *identity = find_ident(type->bases[u], name);
  242. if (identity)
  243. return identity->module->name;
  244. }
  245. return NULL;
  246. }
  247. static bool_t pline_parse_module(const struct lys_module *module, faux_argv_t *argv,
  248. pline_t *pline)
  249. {
  250. faux_argv_node_t *arg = faux_argv_iter(argv);
  251. const struct lysc_node *node = NULL;
  252. char *rollback_xpath = NULL;
  253. // Rollback is a mechanism to roll to previous node while
  254. // oneliners parsing
  255. bool_t rollback = BOOL_FALSE;
  256. pexpr_t *first_pexpr = NULL;
  257. // It's necessary because upper function can use the same pline object
  258. // for another modules before. It uses the same object to collect
  259. // possible completions. But pline is really invalid only when all
  260. // modules don't recognize argument.
  261. pline->invalid = BOOL_FALSE;
  262. do {
  263. pexpr_t *pexpr = pline_current_expr(pline);
  264. const char *str = (const char *)faux_argv_current(arg);
  265. bool_t is_rollback = rollback;
  266. bool_t next_arg = BOOL_TRUE;
  267. rollback = BOOL_FALSE;
  268. if (node && !is_rollback) {
  269. char *tmp = NULL;
  270. // Save rollback Xpath (for oneliners) before leaf node
  271. // Only leaf and leaf-list node allows to "rollback"
  272. // the path and add additional statements
  273. if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
  274. faux_str_free(rollback_xpath);
  275. rollback_xpath = faux_str_dup(pexpr->xpath);
  276. }
  277. // Add current node to Xpath
  278. tmp = faux_str_sprintf("/%s:%s",
  279. node->module->name, node->name);
  280. faux_str_cat(&pexpr->xpath, tmp);
  281. faux_str_free(tmp);
  282. pexpr->args_num++;
  283. // Activate current expression. Because it really has
  284. // new component
  285. pexpr->active = BOOL_TRUE;
  286. }
  287. // Root of the module
  288. if (!node) {
  289. // Completion
  290. if (!str) {
  291. pline_add_compl_subtree(pline, module, node);
  292. break;
  293. }
  294. // Next element
  295. node = find_child(module->compiled->data, str);
  296. if (!node)
  297. break;
  298. // Container
  299. } else if (node->nodetype & LYS_CONTAINER) {
  300. pexpr->pat = PAT_CONTAINER;
  301. // Completion
  302. if (!str) {
  303. pline_add_compl_subtree(pline, module, node);
  304. break;
  305. }
  306. // Next element
  307. node = find_child(lysc_node_child(node), str);
  308. // List
  309. } else if (node->nodetype & LYS_LIST) {
  310. const struct lysc_node *iter = NULL;
  311. pexpr->pat = PAT_LIST;
  312. pexpr->list_pos = pexpr->args_num;
  313. // Next element
  314. if (!is_rollback) {
  315. bool_t break_upper_loop = BOOL_FALSE;
  316. LY_LIST_FOR(lysc_node_child(node), iter) {
  317. char *tmp = NULL;
  318. struct lysc_node_leaf *leaf =
  319. (struct lysc_node_leaf *)iter;
  320. if (!(iter->nodetype & LYS_LEAF))
  321. continue;
  322. if (!(iter->flags & LYS_KEY))
  323. continue;
  324. assert (leaf->type->basetype != LY_TYPE_EMPTY);
  325. // Completion
  326. if (!str) {
  327. char *tmp = NULL;
  328. tmp = faux_str_sprintf("%s/%s",
  329. pexpr->xpath, leaf->name);
  330. pline_add_compl(pline,
  331. PCOMPL_TYPE, iter, tmp);
  332. faux_str_free(tmp);
  333. break_upper_loop = BOOL_TRUE;
  334. break;
  335. }
  336. tmp = faux_str_sprintf("[%s='%s']",
  337. leaf->name, str);
  338. faux_str_cat(&pexpr->xpath, tmp);
  339. faux_str_free(tmp);
  340. pexpr->args_num++;
  341. faux_argv_each(&arg);
  342. str = (const char *)faux_argv_current(arg);
  343. pexpr->pat = PAT_LIST_KEY_INCOMPLETED;
  344. }
  345. if (break_upper_loop)
  346. break;
  347. }
  348. pexpr->pat = PAT_LIST_KEY;
  349. // Completion
  350. if (!str) {
  351. pline_add_compl_subtree(pline, module, node);
  352. break;
  353. }
  354. // Next element
  355. node = find_child(lysc_node_child(node), str);
  356. // Leaf
  357. } else if (node->nodetype & LYS_LEAF) {
  358. struct lysc_node_leaf *leaf =
  359. (struct lysc_node_leaf *)node;
  360. // Next element
  361. if (LY_TYPE_EMPTY == leaf->type->basetype) {
  362. pexpr->pat = PAT_LEAF_EMPTY;
  363. // Completion
  364. if (!str) {
  365. pline_add_compl_subtree(pline,
  366. module, node->parent);
  367. break;
  368. }
  369. // Don't get next argument when argument is not
  370. // really consumed
  371. next_arg = BOOL_FALSE;
  372. } else {
  373. pexpr->pat = PAT_LEAF;
  374. // Completion
  375. if (!str) {
  376. pline_add_compl(pline,
  377. PCOMPL_TYPE, node, NULL);
  378. break;
  379. }
  380. pexpr->pat = PAT_LEAF_VALUE;
  381. // Idenity must have prefix
  382. if (LY_TYPE_IDENT == leaf->type->basetype) {
  383. const char *prefix = NULL;
  384. prefix = identityref_prefix(
  385. (struct lysc_type_identityref *)
  386. leaf->type, str);
  387. if (prefix)
  388. pexpr->value = faux_str_sprintf(
  389. "%s:", prefix);
  390. }
  391. faux_str_cat(&pexpr->value, str);
  392. }
  393. // Expression was completed
  394. // So rollback (for oneliners)
  395. node = node->parent;
  396. pline_add_expr(pline, rollback_xpath);
  397. rollback = BOOL_TRUE;
  398. // Leaf-list
  399. } else if (node->nodetype & LYS_LEAFLIST) {
  400. char *tmp = NULL;
  401. const char *prefix = NULL;
  402. struct lysc_node_leaflist *leaflist =
  403. (struct lysc_node_leaflist *)node;
  404. pexpr->pat = PAT_LEAFLIST;
  405. pexpr->list_pos = pexpr->args_num;
  406. // Completion
  407. if (!str) {
  408. pline_add_compl(pline,
  409. PCOMPL_TYPE, node, pexpr->xpath);
  410. break;
  411. }
  412. pexpr->pat = PAT_LEAFLIST_VALUE;
  413. // Idenity must have prefix
  414. if (LY_TYPE_IDENT == leaflist->type->basetype) {
  415. prefix = identityref_prefix(
  416. (struct lysc_type_identityref *)
  417. leaflist->type, str);
  418. }
  419. tmp = faux_str_sprintf("[.='%s%s%s']",
  420. prefix ? prefix : "", prefix ? ":" : "", str);
  421. faux_str_cat(&pexpr->xpath, tmp);
  422. faux_str_free(tmp);
  423. pexpr->args_num++;
  424. // Expression was completed
  425. // So rollback (for oneliners)
  426. node = node->parent;
  427. pline_add_expr(pline, rollback_xpath);
  428. rollback = BOOL_TRUE;
  429. }
  430. // Current argument was not consumed.
  431. // Break before getting next arg.
  432. if (!node && !rollback)
  433. break;
  434. if (next_arg)
  435. faux_argv_each(&arg);
  436. } while (BOOL_TRUE);
  437. // There is not-consumed argument so whole pline is invalid
  438. if (faux_argv_current(arg))
  439. pline->invalid = BOOL_TRUE;
  440. faux_str_free(rollback_xpath);
  441. first_pexpr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  442. if (!first_pexpr || !first_pexpr->xpath)
  443. return BOOL_FALSE; // Not found
  444. return BOOL_TRUE;
  445. }
  446. pline_t *pline_parse(sr_session_ctx_t *sess, faux_argv_t *argv, uint32_t flags)
  447. {
  448. const struct ly_ctx *ctx = NULL;
  449. struct lys_module *module = NULL;
  450. pline_t *pline = NULL;
  451. uint32_t i = 0;
  452. faux_list_node_t *last_expr_node = NULL;
  453. assert(sess);
  454. if (!sess)
  455. return NULL;
  456. pline = pline_new(sess);
  457. if (!pline)
  458. return NULL;
  459. ctx = sr_session_acquire_context(pline->sess);
  460. if (!ctx)
  461. return NULL;
  462. // Iterate all modules
  463. i = 0;
  464. while ((module = ly_ctx_get_module_iter(ctx, &i))) {
  465. if (sr_module_is_internal(module))
  466. continue;
  467. if (!module->compiled)
  468. continue;
  469. if (!module->implemented)
  470. continue;
  471. if (!module->compiled->data)
  472. continue;
  473. if (pline_parse_module(module, argv, pline))
  474. break; // Found
  475. }
  476. sr_session_release_context(pline->sess);
  477. // Last parsed expression can be inactive so remove it from list
  478. last_expr_node = faux_list_tail(pline->exprs);
  479. if (last_expr_node) {
  480. pexpr_t *expr = (pexpr_t *)faux_list_data(last_expr_node);
  481. if (!expr->active)
  482. faux_list_del(pline->exprs, last_expr_node);
  483. }
  484. return pline;
  485. }
  486. static void identityref(struct lysc_ident *ident)
  487. {
  488. LY_ARRAY_COUNT_TYPE u = 0;
  489. if (!ident)
  490. return;
  491. if (!ident->derived) {
  492. printf("%s\n", ident->name);
  493. return;
  494. }
  495. LY_ARRAY_FOR(ident->derived, u) {
  496. identityref(ident->derived[u]);
  497. }
  498. }
  499. static void pline_print_type_completions(const struct lysc_type *type)
  500. {
  501. assert(type);
  502. switch (type->basetype) {
  503. case LY_TYPE_BOOL: {
  504. printf("true\nfalse\n");
  505. break;
  506. }
  507. case LY_TYPE_ENUM: {
  508. const struct lysc_type_enum *t =
  509. (const struct lysc_type_enum *)type;
  510. LY_ARRAY_COUNT_TYPE u = 0;
  511. LY_ARRAY_FOR(t->enums, u) {
  512. printf("%s\n",t->enums[u].name);
  513. }
  514. break;
  515. }
  516. case LY_TYPE_IDENT: {
  517. struct lysc_type_identityref *t =
  518. (struct lysc_type_identityref *)type;
  519. LY_ARRAY_COUNT_TYPE u = 0;
  520. LY_ARRAY_FOR(t->bases, u) {
  521. identityref(t->bases[u]);
  522. }
  523. break;
  524. }
  525. case LY_TYPE_UNION: {
  526. struct lysc_type_union *t =
  527. (struct lysc_type_union *)type;
  528. LY_ARRAY_COUNT_TYPE u = 0;
  529. LY_ARRAY_FOR(t->types, u) {
  530. pline_print_type_completions(t->types[u]);
  531. }
  532. break;
  533. }
  534. default:
  535. break;
  536. }
  537. }
  538. static void pline_print_type_help(const struct lysc_node *node,
  539. const struct lysc_type *type)
  540. {
  541. assert(type);
  542. if (type->basetype != LY_TYPE_UNION)
  543. printf("%s\n", node->name);
  544. switch (type->basetype) {
  545. case LY_TYPE_UINT8: {
  546. printf("Unsigned integer 8bit\n");
  547. break;
  548. }
  549. case LY_TYPE_UINT16: {
  550. printf("Unsigned integer 16bit\n");
  551. break;
  552. }
  553. case LY_TYPE_UINT32: {
  554. printf("Unsigned integer 32bit\n");
  555. break;
  556. }
  557. case LY_TYPE_UINT64: {
  558. printf("Unsigned integer 64bit\n");
  559. break;
  560. }
  561. case LY_TYPE_INT8: {
  562. printf("Integer 8bit\n");
  563. break;
  564. }
  565. case LY_TYPE_INT16: {
  566. printf("Integer 16bit\n");
  567. break;
  568. }
  569. case LY_TYPE_INT32: {
  570. printf("Integer 32bit\n");
  571. break;
  572. }
  573. case LY_TYPE_INT64: {
  574. printf("Integer 64bit\n");
  575. break;
  576. }
  577. case LY_TYPE_STRING: {
  578. printf("String\n");
  579. break;
  580. }
  581. case LY_TYPE_BOOL: {
  582. printf("Boolean true/false\n");
  583. break;
  584. }
  585. case LY_TYPE_DEC64: {
  586. printf("Signed decimal number\n");
  587. break;
  588. }
  589. case LY_TYPE_ENUM: {
  590. printf("Enumerated choice\n");
  591. break;
  592. }
  593. case LY_TYPE_IDENT: {
  594. printf("Identity\n");
  595. break;
  596. }
  597. case LY_TYPE_UNION: {
  598. struct lysc_type_union *t =
  599. (struct lysc_type_union *)type;
  600. LY_ARRAY_COUNT_TYPE u = 0;
  601. LY_ARRAY_FOR(t->types, u) {
  602. pline_print_type_help(node, t->types[u]);
  603. }
  604. break;
  605. }
  606. default:
  607. printf("Unknown\n");
  608. break;
  609. }
  610. }
  611. void pline_print_completions(const pline_t *pline, bool_t help)
  612. {
  613. faux_list_node_t *iter = NULL;
  614. pcompl_t *pcompl = NULL;
  615. iter = faux_list_head(pline->compls);
  616. while ((pcompl = (pcompl_t *)faux_list_each(&iter))) {
  617. struct lysc_type *type = NULL;
  618. const struct lysc_node *node = pcompl->node;
  619. if (pcompl->xpath && !help) {
  620. sr_val_t *vals = NULL;
  621. size_t val_num = 0;
  622. size_t i = 0;
  623. sr_get_items(pline->sess, pcompl->xpath,
  624. 0, 0, &vals, &val_num);
  625. for (i = 0; i < val_num; i++) {
  626. char *tmp = sr_val_to_str(&vals[i]);
  627. if (!tmp)
  628. continue;
  629. printf("%s\n", tmp);
  630. free(tmp);
  631. }
  632. }
  633. if (!node)
  634. continue;
  635. // Node
  636. if (PCOMPL_NODE == pcompl->type) {
  637. printf("%s\n", node->name);
  638. if (help) {
  639. if (!node->dsc) {
  640. printf("%s\n", node->name);
  641. } else {
  642. char *dsc = faux_str_getline(node->dsc,
  643. NULL);
  644. printf("%s\n", dsc);
  645. faux_str_free(dsc);
  646. }
  647. }
  648. continue;
  649. }
  650. // Type
  651. if (node->nodetype & LYS_LEAF)
  652. type = ((struct lysc_node_leaf *)node)->type;
  653. else if (node->nodetype & LYS_LEAFLIST)
  654. type = ((struct lysc_node_leaflist *)node)->type;
  655. else
  656. continue;
  657. if (help)
  658. pline_print_type_help(node, type);
  659. else
  660. pline_print_type_completions(type);
  661. }
  662. }