pline.c 14 KB

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