pline.c 15 KB

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