ksession_parse.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /** @file ksession_parse.c
  2. */
  3. #include <assert.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <faux/argv.h>
  8. #include <klish/khelper.h>
  9. #include <klish/kview.h>
  10. #include <klish/kscheme.h>
  11. #include <klish/kpath.h>
  12. #include <klish/kpargv.h>
  13. #include <klish/ksession.h>
  14. static bool_t ksession_validate_arg(kentry_t *entry, const char *arg)
  15. {
  16. const char *str = NULL;
  17. assert(entry);
  18. if (!entry)
  19. return BOOL_FALSE;
  20. assert(arg);
  21. if (!arg)
  22. return BOOL_FALSE;
  23. // Temporary test code that implements COMMAND i.e. it compares argument
  24. // to ENTRY's 'name' or 'value'. Later it will be removed by real code.
  25. str = kentry_value(entry);
  26. if (!str)
  27. str = kentry_name(entry);
  28. if (faux_str_casecmp(str, arg) == 0)
  29. return BOOL_TRUE;
  30. return BOOL_FALSE;
  31. }
  32. static kparse_status_e ksession_parse_arg(kentry_t *current_entry,
  33. faux_argv_node_t **argv_iter, kpargv_t *pargv)
  34. {
  35. kentry_t *entry = current_entry;
  36. kentry_mode_e mode = KENTRY_MODE_NONE;
  37. kparse_status_e retcode = KPARSE_NOTFOUND; // For ENTRY itself
  38. kparse_status_e rc = KPARSE_NOTFOUND; // For nested ENTRYs
  39. assert(current_entry);
  40. if (!current_entry)
  41. return KPARSE_ERROR;
  42. assert(argv_iter);
  43. if (!argv_iter)
  44. return KPARSE_ERROR;
  45. assert(pargv);
  46. if (!pargv)
  47. return KPARSE_ERROR;
  48. // If all arguments are resolved already then return INCOMPLETED
  49. assert(*argv_iter);
  50. if (!*argv_iter)
  51. return KPARSE_INCOMPLETED;
  52. // Is entry candidate to resolve current arg?
  53. // Container can't be a candidate.
  54. if (!kentry_container(entry)) {
  55. const char *current_arg = faux_argv_current(*argv_iter);
  56. if (ksession_validate_arg(entry, current_arg)) {
  57. kparg_t *parg = kparg_new(entry, current_arg);
  58. kpargv_add_parg(pargv, parg);
  59. faux_argv_each(argv_iter); // Next argument
  60. retcode = KPARSE_INPROGRESS;
  61. } else {
  62. // It's not a container and is not validated so
  63. // no chance to find anything here.
  64. return KPARSE_NOTFOUND;
  65. }
  66. }
  67. // ENTRY has no nested ENTRYs so return
  68. if (kentry_entrys_is_empty(entry))
  69. return retcode;
  70. // Walk through the nested entries
  71. mode = kentry_mode(entry);
  72. if (KENTRY_MODE_EMPTY == mode)
  73. return retcode;
  74. // SWITCH
  75. // Entries within SWITCH can't has 'min'/'max' else than 1.
  76. // So these attributes will be ignored. Note SWITCH itself can have
  77. // 'min'/'max'.
  78. if (KENTRY_MODE_SWITCH == mode) {
  79. kentry_entrys_node_t *iter = kentry_entrys_iter(entry);
  80. kentry_t *nested = NULL;
  81. while ((nested = kentry_entrys_each(&iter))) {
  82. rc = ksession_parse_arg(nested, argv_iter, pargv);
  83. // Any variant of error or INPROGRESS
  84. if (rc != KPARSE_NOTFOUND)
  85. break;
  86. }
  87. // SEQUENCE
  88. } else if (KENTRY_MODE_SEQUENCE == mode) {
  89. kentry_entrys_node_t *iter = kentry_entrys_iter(entry);
  90. kentry_entrys_node_t *saved_iter = iter;
  91. kentry_t *nested = NULL;
  92. while ((nested = kentry_entrys_each(&iter))) {
  93. kparse_status_e nrc = KPARSE_NOTFOUND;
  94. size_t num = 0;
  95. size_t min = kentry_min(nested);
  96. printf("Arg: %s, entry %s\n", faux_argv_current(*argv_iter), kentry_name(nested));
  97. // Filter out double parsing for optional entries.
  98. if (kpargv_entry_exists(pargv, nested))
  99. continue;
  100. // Try to match argument and current entry
  101. // (from 'min' to 'max' times)
  102. for (num = 0; num < kentry_max(nested); num++) {
  103. nrc = ksession_parse_arg(nested, argv_iter, pargv);
  104. if (nrc != KPARSE_INPROGRESS)
  105. break;
  106. }
  107. // All errors will break the loop
  108. if ((nrc != KPARSE_INPROGRESS) && (nrc != KPARSE_NOTFOUND)) {
  109. rc = nrc;
  110. break;
  111. }
  112. // Not found all mandatory instances (NOTFOUND)
  113. if (num < min) {
  114. rc = KPARSE_NOTFOUND;
  115. break;
  116. }
  117. // It's not an error if optional parameter is absend
  118. rc = KPARSE_INPROGRESS;
  119. // Mandatory or ordered parameter
  120. if ((min > 0) || kentry_order(nested))
  121. saved_iter = iter;
  122. // If optional entry is found then go back to nearest
  123. // non-optional (or ordered) entry to try to find
  124. // another optional entries.
  125. if ((0 == min) && (num > 0))
  126. iter = saved_iter;
  127. }
  128. }
  129. // When ENTRY (not container) is found but mandatory nested ENTRY is
  130. // not resolved. It's inconsistent. So NOTFOUND is not suitable in
  131. // this case.
  132. if ((KPARSE_NOTFOUND == rc) && (KPARSE_INPROGRESS == retcode))
  133. return KPARSE_ILLEGAL;
  134. return rc;
  135. }
  136. kparse_status_e ksession_parse_line(ksession_t *session, const char *line,
  137. kpargv_t **parsed_argv)
  138. {
  139. faux_argv_t *argv = NULL;
  140. faux_argv_node_t *argv_iter = NULL;
  141. kentry_t *current_entry = NULL;
  142. kpargv_t *pargv = NULL;
  143. kparse_status_e pstatus = KPARSE_NONE;
  144. if (parsed_argv)
  145. *parsed_argv = NULL;
  146. assert(session);
  147. if (!session)
  148. return KPARSE_ERROR;
  149. assert(line);
  150. if (!line)
  151. return KPARSE_ERROR;
  152. // Split line to arguments
  153. argv = faux_argv_new();
  154. assert(argv);
  155. if (!argv)
  156. return KPARSE_ERROR;
  157. if (faux_argv_parse(argv, line) < 0) {
  158. faux_argv_free(argv);
  159. return KPARSE_ERROR;
  160. }
  161. printf("AAAAAAAAAAA %ld\n", faux_argv_len(argv));
  162. argv_iter = faux_argv_iter(argv);
  163. current_entry = klevel_entry(kpath_current(ksession_path(session)));
  164. pargv = kpargv_new();
  165. assert(pargv);
  166. pstatus = ksession_parse_arg(current_entry, &argv_iter, pargv);
  167. // It's a higher level of parsing, so some statuses can have different
  168. // meanings
  169. /* if (KPARSE_NONE == pstatus)
  170. pstatus = KPARSE_ERROR; // Strange case
  171. else if (KPARSE_INPROGRESS == pstatus) {
  172. if (NULL == argv_iter) // All args are parsed
  173. pstatus = KPARSE_OK;
  174. else
  175. pstatus = KPARSE_ILLEGAL; // Additional not parsable args
  176. }
  177. */
  178. printf("KKKKKKKKK %ld\n", kpargv_pargs_len(pargv));
  179. if (kpargv_pargs_is_empty(pargv)) {
  180. kpargv_free(pargv);
  181. pargv = NULL;
  182. }
  183. *parsed_argv = pargv;
  184. return pstatus;
  185. }