pline.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  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_completions(const pline_t *pline, sr_session_ctx_t *sess)
  448. {
  449. faux_list_node_t *iter = NULL;
  450. pcompl_t *pcompl = NULL;
  451. iter = faux_list_head(pline->compls);
  452. while (pcompl = (pcompl_t *)faux_list_each(&iter)) {
  453. struct lysc_type *type = NULL;
  454. const struct lysc_node *node = pcompl->node;
  455. if (pcompl->xpath) {
  456. sr_val_t *vals = NULL;
  457. size_t val_num = 0;
  458. size_t i = 0;
  459. sr_get_items(sess, pcompl->xpath, 0, 0, &vals, &val_num);
  460. for (i = 0; i < val_num; i++) {
  461. char *tmp = sr_val_to_str(&vals[i]);
  462. if (!tmp)
  463. continue;
  464. printf("%s\n", tmp);
  465. free(tmp);
  466. }
  467. }
  468. if (!node)
  469. continue;
  470. // Node
  471. if (PCOMPL_NODE == pcompl->type) {
  472. printf("%s\n", node->name);
  473. continue;
  474. }
  475. // Type
  476. if (node->nodetype & LYS_LEAF)
  477. type = ((struct lysc_node_leaf *)node)->type;
  478. else if (node->nodetype & LYS_LEAFLIST)
  479. type = ((struct lysc_node_leaflist *)node)->type;
  480. else
  481. continue;
  482. pline_print_type_completions(type);
  483. }
  484. }