pline.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607
  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 <syslog.h>
  9. #include <limits.h>
  10. #include <faux/faux.h>
  11. #include <faux/str.h>
  12. #include <faux/list.h>
  13. #include <faux/argv.h>
  14. #include <faux/ini.h>
  15. #include <faux/conv.h>
  16. #include <sysrepo.h>
  17. #include <sysrepo/xpath.h>
  18. #include <sysrepo/values.h>
  19. #include <libyang/tree_edit.h>
  20. #include "klish_plugin_sysrepo.h"
  21. static int sr_ly_module_is_internal(const struct lys_module *ly_mod)
  22. {
  23. if (!ly_mod->revision) {
  24. return 0;
  25. }
  26. if (!strcmp(ly_mod->name, "ietf-yang-metadata")
  27. && !strcmp(ly_mod->revision, "2016-08-05")) {
  28. return 1;
  29. } else if (!strcmp(ly_mod->name, "yang")
  30. && !strcmp(ly_mod->revision, "2021-04-07")) {
  31. return 1;
  32. } else if (!strcmp(ly_mod->name, "ietf-inet-types")
  33. && !strcmp(ly_mod->revision, "2013-07-15")) {
  34. return 1;
  35. } else if (!strcmp(ly_mod->name, "ietf-yang-types")
  36. && !strcmp(ly_mod->revision, "2013-07-15")) {
  37. return 1;
  38. }
  39. return 0;
  40. }
  41. static int sr_module_is_internal(const struct lys_module *ly_mod, bool_t enable_nacm)
  42. {
  43. if (!ly_mod->revision) {
  44. return 0;
  45. }
  46. if (sr_ly_module_is_internal(ly_mod)) {
  47. return 1;
  48. }
  49. if (!strcmp(ly_mod->name, "ietf-datastores")
  50. && !strcmp(ly_mod->revision, "2018-02-14")) {
  51. return 1;
  52. } else if (!strcmp(ly_mod->name, "ietf-yang-schema-mount")) {
  53. return 1;
  54. } else if (!strcmp(ly_mod->name, "ietf-yang-library")) {
  55. return 1;
  56. } else if (!strcmp(ly_mod->name, "ietf-netconf")) {
  57. return 1;
  58. } else if (!strcmp(ly_mod->name, "ietf-netconf-with-defaults")
  59. && !strcmp(ly_mod->revision, "2011-06-01")) {
  60. return 1;
  61. } else if (!strcmp(ly_mod->name, "ietf-origin")
  62. && !strcmp(ly_mod->revision, "2018-02-14")) {
  63. return 1;
  64. } else if (!strcmp(ly_mod->name, "ietf-netconf-notifications")
  65. && !strcmp(ly_mod->revision, "2012-02-06")) {
  66. return 1;
  67. } else if (!strcmp(ly_mod->name, "sysrepo")) {
  68. return 1;
  69. } else if (!strcmp(ly_mod->name, "sysrepo-monitoring")) {
  70. return 1;
  71. } else if (!strcmp(ly_mod->name, "sysrepo-plugind")) {
  72. return 1;
  73. } else if (!strcmp(ly_mod->name, "ietf-netconf-acm") && !enable_nacm) {
  74. return 1;
  75. }
  76. return 0;
  77. }
  78. static pexpr_t *pexpr_new(void)
  79. {
  80. pexpr_t *pexpr = NULL;
  81. pexpr = faux_zmalloc(sizeof(*pexpr));
  82. assert(pexpr);
  83. if (!pexpr)
  84. return NULL;
  85. // Initialize
  86. pexpr->xpath = NULL;
  87. pexpr->value = NULL;
  88. pexpr->active = BOOL_FALSE;
  89. pexpr->pat = PAT_NONE;
  90. pexpr->args_num = 0;
  91. pexpr->list_pos = 0;
  92. pexpr->last_keys = NULL;
  93. return pexpr;
  94. }
  95. static void pexpr_free(pexpr_t *pexpr)
  96. {
  97. if (!pexpr)
  98. return;
  99. faux_str_free(pexpr->xpath);
  100. faux_str_free(pexpr->value);
  101. faux_str_free(pexpr->last_keys);
  102. free(pexpr);
  103. }
  104. static pcompl_t *pcompl_new(void)
  105. {
  106. pcompl_t *pcompl = NULL;
  107. pcompl = faux_zmalloc(sizeof(*pcompl));
  108. assert(pcompl);
  109. if (!pcompl)
  110. return NULL;
  111. // Initialize
  112. pcompl->type = PCOMPL_NODE;
  113. pcompl->node = NULL;
  114. pcompl->xpath = NULL;
  115. pcompl->xpath_ds = SRP_REPO_EDIT;
  116. pcompl->pat = PAT_NONE;
  117. return pcompl;
  118. }
  119. static void pcompl_free(pcompl_t *pcompl)
  120. {
  121. if (!pcompl)
  122. return;
  123. faux_str_free(pcompl->xpath);
  124. free(pcompl);
  125. }
  126. pline_t *pline_new(sr_session_ctx_t *sess)
  127. {
  128. pline_t *pline = NULL;
  129. pline = faux_zmalloc(sizeof(*pline));
  130. assert(pline);
  131. if (!pline)
  132. return NULL;
  133. // Init
  134. pline->sess = sess;
  135. pline->invalid = BOOL_FALSE;
  136. pline->exprs = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
  137. NULL, NULL, (faux_list_free_fn)pexpr_free);
  138. pline->compls = faux_list_new(FAUX_LIST_UNSORTED, FAUX_LIST_NONUNIQUE,
  139. NULL, NULL, (faux_list_free_fn)pcompl_free);
  140. return pline;
  141. }
  142. void pline_free(pline_t *pline)
  143. {
  144. if (!pline)
  145. return;
  146. faux_list_free(pline->exprs);
  147. faux_list_free(pline->compls);
  148. faux_free(pline);
  149. }
  150. static pexpr_t *pline_add_expr(pline_t *pline, const char *xpath,
  151. size_t args_num, size_t list_pos, size_t tree_depth)
  152. {
  153. pexpr_t *pexpr = NULL;
  154. assert(pline);
  155. pexpr = pexpr_new();
  156. if (xpath)
  157. pexpr->xpath = faux_str_dup(xpath);
  158. pexpr->args_num = args_num;
  159. pexpr->list_pos = list_pos;
  160. pexpr->tree_depth = tree_depth;
  161. faux_list_add(pline->exprs, pexpr);
  162. return pexpr;
  163. }
  164. pexpr_t *pline_current_expr(pline_t *pline)
  165. {
  166. assert(pline);
  167. if (faux_list_len(pline->exprs) == 0)
  168. pline_add_expr(pline, NULL, 0, 0, 0);
  169. return (pexpr_t *)faux_list_data(faux_list_tail(pline->exprs));
  170. }
  171. static void pline_add_compl(pline_t *pline,
  172. pcompl_type_e type, const struct lysc_node *node,
  173. const char *xpath, sr_datastore_t ds, pat_e pat)
  174. {
  175. pcompl_t *pcompl = NULL;
  176. assert(pline);
  177. pcompl = pcompl_new();
  178. pcompl->type = type;
  179. pcompl->node = node;
  180. pcompl->pat = pat;
  181. if (xpath) {
  182. pcompl->xpath = faux_str_dup(xpath);
  183. pcompl->xpath_ds = ds;
  184. }
  185. faux_list_add(pline->compls, pcompl);
  186. }
  187. static void pline_add_compl_subtree(pline_t *pline, const struct lys_module *module,
  188. const struct lysc_node *node, const char *xpath)
  189. {
  190. const struct lysc_node *subtree = NULL;
  191. const struct lysc_node *iter = NULL;
  192. assert(pline);
  193. assert(module);
  194. if (node)
  195. subtree = lysc_node_child(node);
  196. else
  197. subtree = module->compiled->data;
  198. LY_LIST_FOR(subtree, iter) {
  199. pat_e pat = PAT_NONE;
  200. char *node_xpath = NULL;
  201. if (!(iter->nodetype & SRP_NODETYPE_CONF))
  202. continue;
  203. if (!(iter->flags & LYS_CONFIG_W))
  204. continue;
  205. if ((iter->nodetype & LYS_LEAF) && (iter->flags & LYS_KEY))
  206. continue;
  207. if (iter->nodetype & (LYS_CHOICE | LYS_CASE)) {
  208. pline_add_compl_subtree(pline, module, iter, xpath);
  209. continue;
  210. }
  211. switch(iter->nodetype) {
  212. case LYS_CONTAINER:
  213. pat = PAT_CONTAINER;
  214. break;
  215. case LYS_LEAF:
  216. pat = PAT_LEAF;
  217. break;
  218. case LYS_LEAFLIST:
  219. pat = PAT_LEAFLIST;
  220. break;
  221. case LYS_LIST:
  222. pat = PAT_LIST;
  223. break;
  224. default:
  225. continue;
  226. break;
  227. }
  228. node_xpath = faux_str_sprintf("%s/%s:%s", xpath ? xpath : "",
  229. iter->module->name, iter->name);
  230. pline_add_compl(pline, PCOMPL_NODE, iter, node_xpath,
  231. SRP_REPO_EDIT, pat);
  232. faux_str_free(node_xpath);
  233. }
  234. }
  235. static const char *pat2str(pat_e pat)
  236. {
  237. const char *str = NULL;
  238. switch (pat) {
  239. case PAT_NONE:
  240. str = "NONE";
  241. break;
  242. case PAT_CONTAINER:
  243. str = "CONTAINER";
  244. break;
  245. case PAT_LIST:
  246. str = "LIST";
  247. break;
  248. case PAT_LIST_KEY:
  249. str = "LIST_KEY";
  250. break;
  251. case PAT_LIST_KEY_INCOMPLETED:
  252. str = "LIST_KEY_INCOMPLETED";
  253. break;
  254. case PAT_LEAF:
  255. str = "LEAF";
  256. break;
  257. case PAT_LEAF_VALUE:
  258. str = "LEAF_VALUE";
  259. break;
  260. case PAT_LEAF_EMPTY:
  261. str = "LEAF_EMPTY";
  262. break;
  263. case PAT_LEAFLIST:
  264. str = "LEAFLIST";
  265. break;
  266. case PAT_LEAFLIST_VALUE:
  267. str = "LEAFLIST_VALUE";
  268. break;
  269. default:
  270. str = "UNKNOWN";
  271. break;
  272. }
  273. return str;
  274. }
  275. void pline_debug(const pline_t *pline)
  276. {
  277. faux_list_node_t *iter = NULL;
  278. pexpr_t *pexpr = NULL;
  279. pcompl_t *pcompl = NULL;
  280. syslog(LOG_ERR, "====== Pline:");
  281. syslog(LOG_ERR, "invalid = %s", pline->invalid ? "true" : "false");
  282. syslog(LOG_ERR, "=== Expressions:");
  283. iter = faux_list_head(pline->exprs);
  284. while ((pexpr = (pexpr_t *)faux_list_each(&iter))) {
  285. syslog(LOG_ERR, "pexpr.xpath = %s", pexpr->xpath ? pexpr->xpath : "NULL");
  286. syslog(LOG_ERR, "pexpr.value = %s", pexpr->value ? pexpr->value : "NULL");
  287. syslog(LOG_ERR, "pexpr.active = %s", pexpr->active ? "true" : "false");
  288. syslog(LOG_ERR, "pexpr.pat = %s", pat2str(pexpr->pat));
  289. syslog(LOG_ERR, "pexpr.args_num = %lu", pexpr->args_num);
  290. syslog(LOG_ERR, "pexpr.list_pos = %lu", pexpr->list_pos);
  291. syslog(LOG_ERR, "pexpr.last_keys = %s", pexpr->last_keys ? pexpr->last_keys : "NULL");
  292. syslog(LOG_ERR, "pexpr.tree_depth = %lu", pexpr->tree_depth);
  293. syslog(LOG_ERR, "---");
  294. }
  295. syslog(LOG_ERR, "=== Completions:");
  296. iter = faux_list_head(pline->compls);
  297. while ((pcompl = (pcompl_t *)faux_list_each(&iter))) {
  298. syslog(LOG_ERR, "pcompl.type = %s", (pcompl->type == PCOMPL_NODE) ?
  299. "PCOMPL_NODE" : "PCOMPL_TYPE");
  300. syslog(LOG_ERR, "pcompl.node = %s", pcompl->node ? pcompl->node->name : "NULL");
  301. syslog(LOG_ERR, "pcompl.xpath = %s", pcompl->xpath ? pcompl->xpath : "NULL");
  302. syslog(LOG_ERR, "pcompl.pat = %s", pat2str(pcompl->pat));
  303. syslog(LOG_ERR, "---");
  304. }
  305. }
  306. static bool_t pexpr_xpath_add_node(pexpr_t *pexpr,
  307. const char *prefix, const char *name)
  308. {
  309. char *tmp = NULL;
  310. assert(pexpr);
  311. assert(prefix);
  312. assert(name);
  313. tmp = faux_str_sprintf("/%s:%s", prefix, name);
  314. faux_str_cat(&pexpr->xpath, tmp);
  315. faux_str_free(tmp);
  316. pexpr->args_num++;
  317. // Activate current expression. Because it really has
  318. // new component
  319. pexpr->active = BOOL_TRUE;
  320. return BOOL_TRUE;
  321. }
  322. static bool_t pexpr_xpath_add_list_key(pexpr_t *pexpr,
  323. const char *key, const char *value, bool_t inc_args_num)
  324. {
  325. char *tmp = NULL;
  326. char *escaped = NULL;
  327. assert(pexpr);
  328. assert(key);
  329. assert(value);
  330. escaped = faux_str_c_esc(value);
  331. tmp = faux_str_sprintf("[%s=\"%s\"]", key, escaped);
  332. faux_str_free(escaped);
  333. faux_str_cat(&pexpr->xpath, tmp);
  334. faux_str_cat(&pexpr->last_keys, tmp);
  335. faux_str_free(tmp);
  336. if (inc_args_num)
  337. pexpr->args_num++;
  338. return BOOL_TRUE;
  339. }
  340. static bool_t pexpr_xpath_add_leaflist_key(pexpr_t *pexpr,
  341. const char *prefix, const char *value)
  342. {
  343. char *tmp = NULL;
  344. assert(pexpr);
  345. assert(value);
  346. tmp = faux_str_sprintf("[.='%s%s%s']",
  347. prefix ? prefix : "", prefix ? ":" : "", value);
  348. faux_str_cat(&pexpr->xpath, tmp);
  349. faux_str_cat(&pexpr->last_keys, value);
  350. faux_str_free(tmp);
  351. pexpr->args_num++;
  352. return BOOL_TRUE;
  353. }
  354. static void pline_add_compl_leafref(pline_t *pline, const struct lysc_node *node,
  355. const struct lysc_type *type, const char *xpath, pat_e pat)
  356. {
  357. if (!type)
  358. return;
  359. if (!node)
  360. return;
  361. if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST)))
  362. return;
  363. switch (type->basetype) {
  364. case LY_TYPE_UNION: {
  365. struct lysc_type_union *t =
  366. (struct lysc_type_union *)type;
  367. LY_ARRAY_COUNT_TYPE u = 0;
  368. LY_ARRAY_FOR(t->types, u) {
  369. pline_add_compl_leafref(pline, node, t->types[u], xpath, pat);
  370. }
  371. break;
  372. }
  373. case LY_TYPE_LEAFREF: {
  374. char *compl_xpath = klysc_leafref_xpath(node, type, xpath);
  375. pline_add_compl(pline, PCOMPL_TYPE, NULL, compl_xpath, SRP_REPO_EDIT, pat);
  376. faux_str_free(compl_xpath);
  377. break;
  378. }
  379. default:
  380. break;
  381. }
  382. }
  383. static void pline_add_compl_leaf(pline_t *pline, const struct lysc_node *node,
  384. const char *xpath, pat_e pat)
  385. {
  386. struct lysc_type *type = NULL;
  387. const char *ext_xpath = NULL;
  388. assert(pline);
  389. if (!pline)
  390. return;
  391. assert(node);
  392. if (!node)
  393. return;
  394. switch (node->nodetype) {
  395. case LYS_LEAF:
  396. type = ((struct lysc_node_leaf *)node)->type;
  397. break;
  398. case LYS_LEAFLIST:
  399. type = ((struct lysc_node_leaflist *)node)->type;
  400. break;
  401. default:
  402. return;
  403. }
  404. ext_xpath = klysc_node_ext_completion(node);
  405. if (ext_xpath) {
  406. const char *raw_xpath = NULL;
  407. sr_datastore_t ds = SRP_REPO_EDIT;
  408. if (kly_parse_ext_xpath(ext_xpath, &raw_xpath, &ds))
  409. pline_add_compl(pline, PCOMPL_TYPE, NULL, raw_xpath, ds, pat);
  410. }
  411. pline_add_compl(pline, PCOMPL_TYPE, node, xpath, SRP_REPO_EDIT, pat);
  412. pline_add_compl_leafref(pline, node, type, xpath, pat);
  413. }
  414. static bool_t pline_parse_module(const struct lys_module *module,
  415. const faux_argv_t *argv, pline_t *pline, const pline_opts_t *opts)
  416. {
  417. faux_argv_node_t *arg = faux_argv_iter(argv);
  418. const struct lysc_node *node = NULL;
  419. char *rollback_xpath = NULL;
  420. size_t rollback_args_num = 0;
  421. size_t rollback_list_pos = 0;
  422. size_t rollback_tree_depth = 0;
  423. // Rollback is a mechanism to roll to previous node while
  424. // oneliners parsing
  425. bool_t rollback = BOOL_FALSE;
  426. pexpr_t *first_pexpr = NULL;
  427. // It's necessary because upper function can use the same pline object
  428. // for another modules before. It uses the same object to collect
  429. // possible completions. But pline is really invalid only when all
  430. // modules don't recognize argument.
  431. pline->invalid = BOOL_FALSE;
  432. do {
  433. pexpr_t *pexpr = pline_current_expr(pline);
  434. const char *str = (const char *)faux_argv_current(arg);
  435. bool_t is_rollback = rollback;
  436. bool_t next_arg = BOOL_TRUE;
  437. rollback = BOOL_FALSE;
  438. if (node && !is_rollback) {
  439. // Save rollback Xpath (for oneliners) before leaf node
  440. // Only leaf and leaf-list node allows to "rollback"
  441. // the path and add additional statements
  442. if (node->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
  443. faux_str_free(rollback_xpath);
  444. rollback_xpath = faux_str_dup(pexpr->xpath);
  445. rollback_args_num = pexpr->args_num;
  446. rollback_list_pos = pexpr->list_pos;
  447. rollback_tree_depth = pexpr->tree_depth;
  448. }
  449. // Add current node to Xpath
  450. pexpr_xpath_add_node(pexpr,
  451. node->module->name, node->name);
  452. }
  453. // Root of the module
  454. if (!node) {
  455. // Completion
  456. if (!str) {
  457. pline_add_compl_subtree(pline, module, node, pexpr->xpath);
  458. break;
  459. }
  460. // Next element
  461. node = klysc_find_child(module->compiled->data, str);
  462. if (!node)
  463. break;
  464. // Container
  465. } else if (node->nodetype & LYS_CONTAINER) {
  466. pexpr->pat = PAT_CONTAINER;
  467. pexpr->tree_depth++;
  468. // Completion
  469. if (!str) {
  470. pline_add_compl_subtree(pline, module, node, pexpr->xpath);
  471. break;
  472. }
  473. // Next element
  474. node = klysc_find_child(lysc_node_child(node), str);
  475. // List
  476. } else if (node->nodetype & LYS_LIST) {
  477. const struct lysc_node *iter = NULL;
  478. pexpr->pat = PAT_LIST;
  479. pexpr->list_pos = pexpr->args_num;
  480. faux_str_free(pexpr->last_keys);
  481. pexpr->last_keys = NULL;
  482. // Next element
  483. if (!is_rollback) {
  484. bool_t break_upper_loop = BOOL_FALSE;
  485. // Keys without statement. Positional parameters.
  486. if (!opts->keys_w_stmt) {
  487. LY_LIST_FOR(lysc_node_child(node), iter) {
  488. struct lysc_node_leaf *leaf =
  489. (struct lysc_node_leaf *)iter;
  490. if (!(iter->nodetype & LYS_LEAF))
  491. continue;
  492. if (!(iter->flags & LYS_KEY))
  493. continue;
  494. assert (leaf->type->basetype != LY_TYPE_EMPTY);
  495. // Completion
  496. if (!str) {
  497. char *tmp = faux_str_sprintf("%s/%s",
  498. pexpr->xpath, leaf->name);
  499. pline_add_compl_leaf(pline, iter,
  500. tmp, PAT_LIST_KEY);
  501. faux_str_free(tmp);
  502. break_upper_loop = BOOL_TRUE;
  503. break;
  504. }
  505. pexpr_xpath_add_list_key(pexpr,
  506. leaf->name, str, BOOL_TRUE);
  507. faux_argv_each(&arg);
  508. str = (const char *)faux_argv_current(arg);
  509. pexpr->pat = PAT_LIST_KEY_INCOMPLETED;
  510. }
  511. // Keys with statements. Arbitrary order of keys.
  512. } else {
  513. faux_list_t *keys = NULL;
  514. unsigned int specified_keys_num = 0;
  515. klysc_key_t *cur_key = NULL;
  516. char *xpath_wo_default_keys = NULL;
  517. bool_t first_key = BOOL_TRUE;
  518. bool_t first_key_is_optional = BOOL_FALSE;
  519. faux_list_node_t *key_iter = NULL;
  520. // List keys
  521. keys = faux_list_new(FAUX_LIST_UNSORTED,
  522. FAUX_LIST_UNIQUE,
  523. klysc_key_compare,
  524. klysc_key_kcompare,
  525. (faux_list_free_fn)faux_free);
  526. LY_LIST_FOR(lysc_node_child(node), iter) {
  527. struct lysc_node_leaf *leaf =
  528. (struct lysc_node_leaf *)iter;
  529. klysc_key_t *key = NULL;
  530. if (!(iter->nodetype & LYS_LEAF))
  531. continue;
  532. if (!(iter->flags & LYS_KEY))
  533. continue;
  534. assert (leaf->type->basetype != LY_TYPE_EMPTY);
  535. key = faux_zmalloc(sizeof(*key));
  536. assert(key);
  537. key->node = iter;
  538. if (opts->default_keys &&
  539. (key->dflt = klysc_node_ext_default(iter))) {
  540. if (first_key)
  541. first_key_is_optional = BOOL_TRUE;
  542. }
  543. faux_list_add(keys, key);
  544. first_key = BOOL_FALSE;
  545. }
  546. while (specified_keys_num < faux_list_len(keys)) {
  547. // First key without statement. Must be mandatory.
  548. if ((0 == specified_keys_num) &&
  549. !opts->first_key_w_stmt &&
  550. !first_key_is_optional) {
  551. cur_key = (klysc_key_t *)faux_list_data(faux_list_head(keys));
  552. } else {
  553. if (!str)
  554. break;
  555. cur_key = faux_list_kfind(keys, str);
  556. if (!cur_key || cur_key->value)
  557. break;
  558. pexpr->args_num++;
  559. faux_argv_each(&arg);
  560. str = (const char *)faux_argv_current(arg);
  561. }
  562. pexpr->pat = PAT_LIST_KEY_INCOMPLETED;
  563. // Completion
  564. if (!str) {
  565. char *tmp = faux_str_sprintf("%s/%s",
  566. pexpr->xpath,
  567. cur_key->node->name);
  568. pline_add_compl_leaf(pline, cur_key->node,
  569. tmp, PAT_LIST_KEY);
  570. faux_str_free(tmp);
  571. break_upper_loop = BOOL_TRUE;
  572. break;
  573. }
  574. pexpr_xpath_add_list_key(pexpr,
  575. cur_key->node->name, str, BOOL_TRUE);
  576. cur_key->value = str;
  577. specified_keys_num++;
  578. faux_argv_each(&arg);
  579. str = (const char *)faux_argv_current(arg);
  580. pexpr->pat = PAT_LIST_KEY_INCOMPLETED;
  581. }
  582. if (break_upper_loop) {
  583. faux_list_free(keys);
  584. break;
  585. }
  586. xpath_wo_default_keys = faux_str_dup(pexpr->xpath);
  587. key_iter = faux_list_head(keys);
  588. while((cur_key = (klysc_key_t *)faux_list_each(&key_iter))) {
  589. if (cur_key->value)
  590. continue;
  591. // Completion
  592. if (!str) {
  593. char *tmp = faux_str_sprintf("%s/%s",
  594. xpath_wo_default_keys,
  595. cur_key->node->name);
  596. pline_add_compl(pline, PCOMPL_NODE,
  597. cur_key->node, tmp,
  598. SRP_REPO_EDIT, PAT_LIST_KEY);
  599. faux_str_free(tmp);
  600. }
  601. if (opts->default_keys && cur_key->dflt) {
  602. pexpr_xpath_add_list_key(pexpr,
  603. cur_key->node->name,
  604. cur_key->dflt, BOOL_FALSE);
  605. pexpr->pat = PAT_LIST_KEY_INCOMPLETED;
  606. } else { // Mandatory key is not specified
  607. break_upper_loop = BOOL_TRUE;
  608. }
  609. }
  610. faux_str_free(xpath_wo_default_keys);
  611. faux_list_free(keys);
  612. }
  613. if (break_upper_loop)
  614. break;
  615. }
  616. pexpr->pat = PAT_LIST_KEY;
  617. pexpr->tree_depth++;
  618. // Completion
  619. if (!str) {
  620. pline_add_compl_subtree(pline, module, node, pexpr->xpath);
  621. break;
  622. }
  623. // Next element
  624. node = klysc_find_child(lysc_node_child(node), str);
  625. // Leaf
  626. } else if (node->nodetype & LYS_LEAF) {
  627. struct lysc_node_leaf *leaf =
  628. (struct lysc_node_leaf *)node;
  629. // Next element
  630. if (LY_TYPE_EMPTY == leaf->type->basetype) {
  631. pexpr->pat = PAT_LEAF_EMPTY;
  632. // Completion
  633. if (!str) {
  634. pline_add_compl_subtree(pline,
  635. module, node->parent, pexpr->xpath);
  636. break;
  637. }
  638. // Don't get next argument when argument is not
  639. // really consumed
  640. next_arg = BOOL_FALSE;
  641. } else {
  642. pexpr->pat = PAT_LEAF;
  643. // Completion
  644. if (!str) {
  645. pline_add_compl_leaf(pline, node,
  646. pexpr->xpath, PAT_LEAF_VALUE);
  647. break;
  648. }
  649. pexpr->pat = PAT_LEAF_VALUE;
  650. // Idenity must have prefix
  651. if (LY_TYPE_IDENT == leaf->type->basetype) {
  652. const char *prefix = NULL;
  653. prefix = klysc_identityref_prefix(
  654. (struct lysc_type_identityref *)
  655. leaf->type, str);
  656. if (prefix)
  657. pexpr->value = faux_str_sprintf(
  658. "%s:", prefix);
  659. }
  660. faux_str_cat(&pexpr->value, str);
  661. }
  662. // Expression was completed
  663. // So rollback (for oneliners)
  664. node = node->parent;
  665. pline_add_expr(pline, rollback_xpath,
  666. rollback_args_num, rollback_list_pos,
  667. rollback_tree_depth);
  668. rollback = BOOL_TRUE;
  669. // Leaf-list
  670. } else if (node->nodetype & LYS_LEAFLIST) {
  671. const char *prefix = NULL;
  672. struct lysc_node_leaflist *leaflist =
  673. (struct lysc_node_leaflist *)node;
  674. pexpr->pat = PAT_LEAFLIST;
  675. pexpr->list_pos = pexpr->args_num;
  676. faux_str_free(pexpr->last_keys);
  677. pexpr->last_keys = NULL;
  678. // Completion
  679. if (!str) {
  680. pline_add_compl_leaf(pline, node,
  681. pexpr->xpath, PAT_LEAFLIST_VALUE);
  682. break;
  683. }
  684. pexpr->pat = PAT_LEAFLIST_VALUE;
  685. // Idenity must have prefix
  686. if (LY_TYPE_IDENT == leaflist->type->basetype) {
  687. prefix = klysc_identityref_prefix(
  688. (struct lysc_type_identityref *)
  689. leaflist->type, str);
  690. }
  691. pexpr_xpath_add_leaflist_key(pexpr, prefix, str);
  692. // Expression was completed
  693. // So rollback (for oneliners)
  694. node = node->parent;
  695. pline_add_expr(pline, rollback_xpath,
  696. rollback_args_num, rollback_list_pos,
  697. rollback_tree_depth);
  698. rollback = BOOL_TRUE;
  699. // LYS_CHOICE and LYS_CASE can appear while rollback only
  700. } else if (node->nodetype & (LYS_CHOICE | LYS_CASE)) {
  701. // Don't set pexpr->pat because CHOICE and CASE can't
  702. // appear within data tree (schema only)
  703. // Completion
  704. if (!str) {
  705. pline_add_compl_subtree(pline, module, node, pexpr->xpath);
  706. break;
  707. }
  708. // Next element
  709. node = klysc_find_child(lysc_node_child(node), str);
  710. } else {
  711. break;
  712. }
  713. // Current argument was not consumed.
  714. // Break before getting next arg.
  715. if (!node && !rollback)
  716. break;
  717. if (next_arg)
  718. faux_argv_each(&arg);
  719. } while (BOOL_TRUE);
  720. // There is not-consumed argument so whole pline is invalid
  721. if (faux_argv_current(arg))
  722. pline->invalid = BOOL_TRUE;
  723. faux_str_free(rollback_xpath);
  724. first_pexpr = (pexpr_t *)faux_list_data(faux_list_head(pline->exprs));
  725. if (!first_pexpr || !first_pexpr->xpath)
  726. return BOOL_FALSE; // Not found
  727. return BOOL_TRUE;
  728. }
  729. pline_t *pline_parse(sr_session_ctx_t *sess, const faux_argv_t *argv,
  730. const pline_opts_t *opts)
  731. {
  732. const struct ly_ctx *ctx = NULL;
  733. struct lys_module *module = NULL;
  734. pline_t *pline = NULL;
  735. uint32_t i = 0;
  736. faux_list_node_t *last_expr_node = NULL;
  737. assert(sess);
  738. if (!sess)
  739. return NULL;
  740. pline = pline_new(sess);
  741. if (!pline)
  742. return NULL;
  743. ctx = sr_session_acquire_context(pline->sess);
  744. if (!ctx)
  745. return NULL;
  746. // Iterate all modules
  747. i = 0;
  748. while ((module = ly_ctx_get_module_iter(ctx, &i))) {
  749. if (sr_module_is_internal(module, opts->enable_nacm))
  750. continue;
  751. if (!module->compiled)
  752. continue;
  753. if (!module->implemented)
  754. continue;
  755. if (!module->compiled->data)
  756. continue;
  757. if (pline_parse_module(module, argv, pline, opts))
  758. break; // Found
  759. }
  760. sr_session_release_context(pline->sess);
  761. // Last parsed expression can be inactive so remove it from list
  762. last_expr_node = faux_list_tail(pline->exprs);
  763. if (last_expr_node) {
  764. pexpr_t *expr = (pexpr_t *)faux_list_data(last_expr_node);
  765. if (!expr->active)
  766. faux_list_del(pline->exprs, last_expr_node);
  767. }
  768. return pline;
  769. }
  770. static void identityref_compl(struct lysc_ident *ident)
  771. {
  772. LY_ARRAY_COUNT_TYPE u = 0;
  773. if (!ident)
  774. return;
  775. if (!ident->derived) {
  776. printf("%s\n", ident->name);
  777. return;
  778. }
  779. LY_ARRAY_FOR(ident->derived, u) {
  780. identityref_compl(ident->derived[u]);
  781. }
  782. }
  783. static void identityref_help(struct lysc_ident *ident)
  784. {
  785. LY_ARRAY_COUNT_TYPE u = 0;
  786. if (!ident)
  787. return;
  788. if (!ident->derived) {
  789. if (ident->dsc) {
  790. char *dsc = faux_str_getline(ident->dsc, NULL);
  791. printf("%s\n%s\n", ident->name, dsc);
  792. faux_str_free(dsc);
  793. } else {
  794. printf("%s\n%s\n", ident->name, ident->name);
  795. }
  796. return;
  797. }
  798. LY_ARRAY_FOR(ident->derived, u) {
  799. identityref_help(ident->derived[u]);
  800. }
  801. }
  802. static void pline_print_type_completions(const struct lysc_type *type)
  803. {
  804. assert(type);
  805. switch (type->basetype) {
  806. case LY_TYPE_BOOL: {
  807. printf("true\nfalse\n");
  808. break;
  809. }
  810. case LY_TYPE_ENUM: {
  811. const struct lysc_type_enum *t =
  812. (const struct lysc_type_enum *)type;
  813. LY_ARRAY_COUNT_TYPE u = 0;
  814. LY_ARRAY_FOR(t->enums, u) {
  815. printf("%s\n",t->enums[u].name);
  816. }
  817. break;
  818. }
  819. case LY_TYPE_IDENT: {
  820. struct lysc_type_identityref *t =
  821. (struct lysc_type_identityref *)type;
  822. LY_ARRAY_COUNT_TYPE u = 0;
  823. LY_ARRAY_FOR(t->bases, u) {
  824. identityref_compl(t->bases[u]);
  825. }
  826. break;
  827. }
  828. case LY_TYPE_UNION: {
  829. struct lysc_type_union *t =
  830. (struct lysc_type_union *)type;
  831. LY_ARRAY_COUNT_TYPE u = 0;
  832. LY_ARRAY_FOR(t->types, u) {
  833. pline_print_type_completions(t->types[u]);
  834. }
  835. break;
  836. }
  837. case LY_TYPE_LEAFREF: {
  838. struct lysc_type_leafref *t =
  839. (struct lysc_type_leafref *)type;
  840. pline_print_type_completions(t->realtype);
  841. break;
  842. }
  843. default:
  844. break;
  845. }
  846. }
  847. static void uint_range(const struct lysc_type *type, uint64_t def_min, uint64_t def_max)
  848. {
  849. struct lysc_range *range = NULL;
  850. LY_ARRAY_COUNT_TYPE u = 0;
  851. char *r = NULL;
  852. assert(type);
  853. range = ((struct lysc_type_num *)type)->range;
  854. // Show defaults
  855. if (!range) {
  856. printf("[%" PRIu64 "..%" PRIu64 "]\n", def_min, def_max);
  857. return;
  858. }
  859. // Range
  860. faux_str_cat(&r, "[");
  861. LY_ARRAY_FOR(range->parts, u) {
  862. char *t = NULL;
  863. if (u != 0)
  864. faux_str_cat(&r, "|");
  865. t = faux_str_sprintf("%" PRIu64 "..%" PRIu64,
  866. range->parts[u].min_u64, range->parts[u].max_u64);
  867. faux_str_cat(&r, t);
  868. faux_str_free(t);
  869. }
  870. faux_str_cat(&r, "]\n");
  871. printf("%s", r);
  872. faux_free(r);
  873. }
  874. static void int_range(const struct lysc_type *type, int64_t def_min, int64_t def_max)
  875. {
  876. struct lysc_range *range = NULL;
  877. LY_ARRAY_COUNT_TYPE u = 0;
  878. char *r = NULL;
  879. assert(type);
  880. range = ((struct lysc_type_num *)type)->range;
  881. // Show defaults
  882. if (!range) {
  883. printf("[%" PRId64 "..%" PRId64 "]\n", def_min, def_max);
  884. return;
  885. }
  886. // Range
  887. faux_str_cat(&r, "[");
  888. LY_ARRAY_FOR(range->parts, u) {
  889. char *t = NULL;
  890. if (u != 0)
  891. faux_str_cat(&r, "|");
  892. t = faux_str_sprintf("%" PRId64 "..%" PRId64,
  893. range->parts[u].min_64, range->parts[u].max_64);
  894. faux_str_cat(&r, t);
  895. faux_str_free(t);
  896. }
  897. faux_str_cat(&r, "]\n");
  898. printf("%s", r);
  899. faux_free(r);
  900. }
  901. static void dec_range(const struct lysc_type *type, int64_t def_min, int64_t def_max)
  902. {
  903. struct lysc_range *range = NULL;
  904. uint8_t fraction_digits = 0;
  905. LY_ARRAY_COUNT_TYPE u = 0;
  906. char *r = NULL;
  907. int64_t div = 1;
  908. uint8_t i = 0;
  909. assert(type);
  910. range = ((struct lysc_type_dec *)type)->range;
  911. fraction_digits = ((struct lysc_type_dec *)type)->fraction_digits;
  912. for (i = 0; i < fraction_digits; i++)
  913. div = div * 10;
  914. // Show defaults
  915. if (!range) {
  916. printf("[%.*f..%.*f]\n",
  917. fraction_digits, (double)def_min / div,
  918. fraction_digits, (double)def_max / div);
  919. return;
  920. }
  921. // Range
  922. faux_str_cat(&r, "[");
  923. LY_ARRAY_FOR(range->parts, u) {
  924. char *t = NULL;
  925. if (u != 0)
  926. faux_str_cat(&r, "|");
  927. t = faux_str_sprintf("%.*f..%.*f",
  928. fraction_digits, (double)range->parts[u].min_64 / div,
  929. fraction_digits, (double)range->parts[u].max_64 / div);
  930. faux_str_cat(&r, t);
  931. faux_str_free(t);
  932. }
  933. faux_str_cat(&r, "]\n");
  934. printf("%s", r);
  935. faux_free(r);
  936. }
  937. static void str_range(const struct lysc_type *type)
  938. {
  939. struct lysc_range *range = NULL;
  940. LY_ARRAY_COUNT_TYPE u = 0;
  941. char *r = NULL;
  942. assert(type);
  943. range = ((struct lysc_type_str *)type)->length;
  944. // Show defaults
  945. if (!range) {
  946. printf("<string>\n");
  947. return;
  948. }
  949. // Range
  950. faux_str_cat(&r, "<string[");
  951. LY_ARRAY_FOR(range->parts, u) {
  952. char *t = NULL;
  953. if (u != 0)
  954. faux_str_cat(&r, "|");
  955. t = faux_str_sprintf("%" PRIu64 "..%" PRIu64,
  956. range->parts[u].min_u64, range->parts[u].max_u64);
  957. faux_str_cat(&r, t);
  958. faux_str_free(t);
  959. }
  960. faux_str_cat(&r, "]>\n");
  961. printf("%s", r);
  962. faux_free(r);
  963. }
  964. static void pline_print_type_help(const struct lysc_node *node,
  965. const struct lysc_type *type)
  966. {
  967. const char *units = NULL;
  968. assert(type);
  969. assert(node);
  970. if (node->nodetype & LYS_LEAF)
  971. units = ((struct lysc_node_leaf *)node)->units;
  972. else if (node->nodetype & LYS_LEAFLIST)
  973. units = ((struct lysc_node_leaflist *)node)->units;
  974. else
  975. return;
  976. if (units) {
  977. printf("%s\n", units);
  978. } else {
  979. switch (type->basetype) {
  980. case LY_TYPE_UINT8:
  981. uint_range(type, 0, UCHAR_MAX);
  982. break;
  983. case LY_TYPE_UINT16:
  984. uint_range(type, 0, USHRT_MAX);
  985. break;
  986. case LY_TYPE_UINT32:
  987. uint_range(type, 0, UINT_MAX);
  988. break;
  989. case LY_TYPE_UINT64:
  990. uint_range(type, 0, ULLONG_MAX);
  991. break;
  992. case LY_TYPE_INT8:
  993. int_range(type, CHAR_MIN, CHAR_MAX);
  994. break;
  995. case LY_TYPE_INT16:
  996. int_range(type, SHRT_MIN, SHRT_MAX);
  997. break;
  998. case LY_TYPE_INT32:
  999. int_range(type, INT_MIN, INT_MAX);
  1000. break;
  1001. case LY_TYPE_INT64:
  1002. int_range(type, LLONG_MIN, LLONG_MAX);
  1003. break;
  1004. case LY_TYPE_DEC64:
  1005. dec_range(type, LLONG_MIN, LLONG_MAX);
  1006. break;
  1007. case LY_TYPE_STRING:
  1008. str_range(type);
  1009. break;
  1010. case LY_TYPE_BOOL:
  1011. printf("<true/false>\n");
  1012. break;
  1013. case LY_TYPE_LEAFREF: {
  1014. const struct lysc_type_leafref *t =
  1015. (const struct lysc_type_leafref *)type;
  1016. const struct lysc_node *ref_node = NULL;
  1017. const struct lysc_type *ref_type = NULL;
  1018. char *node_path = lysc_path(node, LYSC_PATH_LOG, NULL, 0);
  1019. char *path = klysc_leafref_xpath(node, type, node_path);
  1020. faux_str_free(node_path);
  1021. ref_node = lys_find_path(NULL, node, path, 0);
  1022. faux_str_free(path);
  1023. if (!ref_node) {
  1024. pline_print_type_help(node, t->realtype);
  1025. return; // Because it prints whole info itself
  1026. }
  1027. if (ref_node->nodetype & LYS_LEAF)
  1028. ref_type = ((struct lysc_node_leaf *)ref_node)->type;
  1029. else
  1030. ref_type = ((struct lysc_node_leaflist *)ref_node)->type;
  1031. pline_print_type_help(ref_node, ref_type);
  1032. return; // Because it prints whole info itself
  1033. }
  1034. case LY_TYPE_UNION: {
  1035. const struct lysc_type_union *t =
  1036. (const struct lysc_type_union *)type;
  1037. LY_ARRAY_COUNT_TYPE u = 0;
  1038. LY_ARRAY_FOR(t->types, u)
  1039. pline_print_type_help(node, t->types[u]);
  1040. return; // Because it prints whole info itself
  1041. }
  1042. case LY_TYPE_ENUM: {
  1043. const struct lysc_type_enum *t =
  1044. (const struct lysc_type_enum *)type;
  1045. LY_ARRAY_COUNT_TYPE u = 0;
  1046. LY_ARRAY_FOR(t->enums, u)
  1047. if (t->enums[u].dsc) {
  1048. char *dsc = faux_str_getline(
  1049. t->enums[u].dsc, NULL);
  1050. printf("%s\n%s\n",
  1051. t->enums[u].name, dsc);
  1052. faux_str_free(dsc);
  1053. } else {
  1054. printf("%s\n%s\n",
  1055. t->enums[u].name,
  1056. t->enums[u].name);
  1057. }
  1058. return; // Because it prints whole info itself
  1059. }
  1060. case LY_TYPE_IDENT: {
  1061. struct lysc_type_identityref *t =
  1062. (struct lysc_type_identityref *)type;
  1063. LY_ARRAY_COUNT_TYPE u = 0;
  1064. LY_ARRAY_FOR(t->bases, u)
  1065. identityref_help(t->bases[u]);
  1066. return; // Because it prints whole info itself
  1067. }
  1068. default:
  1069. printf("<unknown>\n");
  1070. break;
  1071. }
  1072. }
  1073. if (node->dsc) {
  1074. char *dsc = faux_str_getline(node->dsc, NULL);
  1075. printf("%s\n", dsc);
  1076. faux_str_free(dsc);
  1077. } else {
  1078. printf("%s\n", node->name);
  1079. }
  1080. }
  1081. static bool_t pline_node_exists(sr_session_ctx_t* sess, const char *xpath)
  1082. {
  1083. sr_val_t *vals = NULL;
  1084. size_t val_num = 0;
  1085. bool_t found = BOOL_FALSE;
  1086. size_t i = 0;
  1087. if (!xpath)
  1088. return BOOL_FALSE;
  1089. sr_get_items(sess, xpath, 0, 0, &vals, &val_num);
  1090. for (i = 0; i < val_num; i++) {
  1091. // Engine can find defaults for entries but not entries themself
  1092. if (!vals[i].dflt) {
  1093. found = BOOL_TRUE;
  1094. break;
  1095. }
  1096. }
  1097. sr_free_values(vals, val_num);
  1098. return found;
  1099. }
  1100. void pline_print_completions(const pline_t *pline, bool_t help,
  1101. pt_e enabled_types, bool_t existing_nodes_only)
  1102. {
  1103. faux_list_node_t *iter = NULL;
  1104. pcompl_t *pcompl = NULL;
  1105. sr_datastore_t current_ds = SRP_REPO_EDIT;
  1106. iter = faux_list_head(pline->compls);
  1107. while ((pcompl = (pcompl_t *)faux_list_each(&iter))) {
  1108. struct lysc_type *type = NULL;
  1109. const struct lysc_node *node = pcompl->node;
  1110. if (!(pcompl->pat & enabled_types))
  1111. continue;
  1112. // Switch to necessary DS
  1113. if (pcompl->xpath && (current_ds != pcompl->xpath_ds)) {
  1114. sr_session_switch_ds(pline->sess, pcompl->xpath_ds);
  1115. current_ds = pcompl->xpath_ds;
  1116. }
  1117. // Help
  1118. if (help) {
  1119. // Note we can't show help without valid node
  1120. if (!node)
  1121. continue;
  1122. // Type (help)
  1123. if (pcompl->type == PCOMPL_TYPE) {
  1124. if (node->nodetype & LYS_LEAF)
  1125. type = ((struct lysc_node_leaf *)node)->type;
  1126. else if (node->nodetype & LYS_LEAFLIST)
  1127. type = ((struct lysc_node_leaflist *)node)->type;
  1128. else
  1129. continue;
  1130. pline_print_type_help(node, type);
  1131. continue;
  1132. }
  1133. // Check node for existing if necessary
  1134. if (existing_nodes_only &&
  1135. !pline_node_exists(pline->sess, pcompl->xpath)) {
  1136. continue;
  1137. }
  1138. // Node (help)
  1139. if (!node->dsc) {
  1140. printf("%s\n%s\n", node->name, node->name);
  1141. } else {
  1142. char *dsc = faux_str_getline(node->dsc,
  1143. NULL);
  1144. printf("%s\n%s\n", node->name, dsc);
  1145. faux_str_free(dsc);
  1146. }
  1147. // Completion
  1148. } else {
  1149. // Type (completion)
  1150. if (pcompl->type == PCOMPL_TYPE) {
  1151. // Existing entries
  1152. if (pcompl->xpath) {
  1153. size_t i = 0;
  1154. sr_val_t *vals = NULL;
  1155. size_t val_num = 0;
  1156. sr_get_items(pline->sess, pcompl->xpath,
  1157. 0, 0, &vals, &val_num);
  1158. for (i = 0; i < val_num; i++) {
  1159. char *tmp = sr_val_to_str(&vals[i]);
  1160. char *esc_tmp = NULL;
  1161. if (!tmp)
  1162. continue;
  1163. esc_tmp = faux_str_c_esc_space(tmp);
  1164. free(tmp);
  1165. printf("%s\n", esc_tmp);
  1166. free(esc_tmp);
  1167. }
  1168. sr_free_values(vals, val_num);
  1169. }
  1170. if (!node)
  1171. continue;
  1172. if (existing_nodes_only)
  1173. continue;
  1174. // All entries
  1175. if (node->nodetype & LYS_LEAF)
  1176. type = ((struct lysc_node_leaf *)node)->type;
  1177. else if (node->nodetype & LYS_LEAFLIST)
  1178. type = ((struct lysc_node_leaflist *)node)->type;
  1179. else
  1180. continue;
  1181. pline_print_type_completions(type);
  1182. continue;
  1183. }
  1184. // Node (completion)
  1185. if (!node)
  1186. continue;
  1187. // Existing entries
  1188. if (existing_nodes_only &&
  1189. !pline_node_exists(pline->sess, pcompl->xpath)) {
  1190. continue;
  1191. }
  1192. printf("%s\n", node->name);
  1193. } // Completion
  1194. } // while
  1195. // Restore default DS
  1196. if (current_ds != SRP_REPO_EDIT)
  1197. sr_session_switch_ds(pline->sess, SRP_REPO_EDIT);
  1198. }
  1199. void pline_opts_init(pline_opts_t *opts)
  1200. {
  1201. opts->begin_bracket = '{';
  1202. opts->end_bracket = '}';
  1203. opts->show_brackets = BOOL_TRUE;
  1204. opts->show_semicolons = BOOL_TRUE;
  1205. opts->first_key_w_stmt = BOOL_FALSE;
  1206. opts->keys_w_stmt = BOOL_TRUE;
  1207. opts->colorize = BOOL_TRUE;
  1208. opts->indent = 2;
  1209. opts->default_keys = BOOL_FALSE;
  1210. opts->show_default_keys = BOOL_FALSE;
  1211. opts->hide_passwords = BOOL_TRUE;
  1212. opts->enable_nacm = BOOL_FALSE;
  1213. opts->oneliners = BOOL_TRUE;
  1214. }
  1215. static int pline_opts_parse_ini(const faux_ini_t *ini, pline_opts_t *opts)
  1216. {
  1217. const char *val = NULL;
  1218. if (!opts)
  1219. return -1;
  1220. if (!ini)
  1221. return 0; // Nothing to parse
  1222. if ((val = faux_ini_find(ini, "ShowBrackets"))) {
  1223. if (faux_str_cmp(val, "y") == 0)
  1224. opts->show_brackets = BOOL_TRUE;
  1225. else if (faux_str_cmp(val, "n") == 0)
  1226. opts->show_brackets = BOOL_FALSE;
  1227. }
  1228. if ((val = faux_ini_find(ini, "ShowSemicolons"))) {
  1229. if (faux_str_cmp(val, "y") == 0)
  1230. opts->show_semicolons = BOOL_TRUE;
  1231. else if (faux_str_cmp(val, "n") == 0)
  1232. opts->show_semicolons = BOOL_FALSE;
  1233. }
  1234. if ((val = faux_ini_find(ini, "FirstKeyWithStatement"))) {
  1235. if (faux_str_cmp(val, "y") == 0)
  1236. opts->first_key_w_stmt = BOOL_TRUE;
  1237. else if (faux_str_cmp(val, "n") == 0)
  1238. opts->first_key_w_stmt = BOOL_FALSE;
  1239. }
  1240. if ((val = faux_ini_find(ini, "KeysWithStatement"))) {
  1241. if (faux_str_cmp(val, "y") == 0)
  1242. opts->keys_w_stmt = BOOL_TRUE;
  1243. else if (faux_str_cmp(val, "n") == 0)
  1244. opts->keys_w_stmt = BOOL_FALSE;
  1245. }
  1246. if ((val = faux_ini_find(ini, "Colorize"))) {
  1247. if (faux_str_cmp(val, "y") == 0)
  1248. opts->colorize = BOOL_TRUE;
  1249. else if (faux_str_cmp(val, "n") == 0)
  1250. opts->colorize = BOOL_FALSE;
  1251. }
  1252. if ((val = faux_ini_find(ini, "Indent"))) {
  1253. unsigned char indent = 0;
  1254. if (faux_conv_atouc(val, &indent, 10))
  1255. opts->indent = indent;
  1256. }
  1257. if ((val = faux_ini_find(ini, "DefaultKeys"))) {
  1258. if (faux_str_cmp(val, "y") == 0)
  1259. opts->default_keys = BOOL_TRUE;
  1260. else if (faux_str_cmp(val, "n") == 0)
  1261. opts->default_keys = BOOL_FALSE;
  1262. }
  1263. if ((val = faux_ini_find(ini, "ShowDefaultKeys"))) {
  1264. if (faux_str_cmp(val, "y") == 0)
  1265. opts->show_default_keys = BOOL_TRUE;
  1266. else if (faux_str_cmp(val, "n") == 0)
  1267. opts->show_default_keys = BOOL_FALSE;
  1268. }
  1269. if ((val = faux_ini_find(ini, "HidePasswords"))) {
  1270. if (faux_str_cmp(val, "y") == 0)
  1271. opts->hide_passwords = BOOL_TRUE;
  1272. else if (faux_str_cmp(val, "n") == 0)
  1273. opts->hide_passwords = BOOL_FALSE;
  1274. }
  1275. if ((val = faux_ini_find(ini, "EnableNACM"))) {
  1276. if (faux_str_cmp(val, "y") == 0)
  1277. opts->enable_nacm = BOOL_TRUE;
  1278. else if (faux_str_cmp(val, "n") == 0)
  1279. opts->enable_nacm = BOOL_FALSE;
  1280. }
  1281. if ((val = faux_ini_find(ini, "Oneliners"))) {
  1282. if (faux_str_cmp(val, "y") == 0)
  1283. opts->oneliners = BOOL_TRUE;
  1284. else if (faux_str_cmp(val, "n") == 0)
  1285. opts->oneliners = BOOL_FALSE;
  1286. }
  1287. return 0;
  1288. }
  1289. int pline_opts_parse(const char *conf, pline_opts_t *opts)
  1290. {
  1291. faux_ini_t *ini = NULL;
  1292. int rc = -1;
  1293. if (!opts)
  1294. return -1;
  1295. if (!conf)
  1296. return 0; // Use defaults
  1297. ini = faux_ini_new();
  1298. if (!faux_ini_parse_str(ini, conf)) {
  1299. faux_ini_free(ini);
  1300. return -1;
  1301. }
  1302. rc = pline_opts_parse_ini(ini, opts);
  1303. faux_ini_free(ini);
  1304. return rc;
  1305. }
  1306. int pline_opts_parse_file(const char *conf_name, pline_opts_t *opts)
  1307. {
  1308. faux_ini_t *ini = NULL;
  1309. int rc = -1;
  1310. if (!opts)
  1311. return -1;
  1312. if (!conf_name)
  1313. return 0; // Use defaults
  1314. ini = faux_ini_new();
  1315. if (!faux_ini_parse_file(ini, conf_name)) {
  1316. faux_ini_free(ini);
  1317. return -1;
  1318. }
  1319. rc = pline_opts_parse_ini(ini, opts);
  1320. faux_ini_free(ini);
  1321. return rc;
  1322. }