repl.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. /* This file is part of ilk.
  2. *
  3. * Ilk is free software: you can redistribute it and/or modify
  4. * it under the terms of the GNU Lesser General Public License as published by
  5. * the Free Software Foundation, either version 3 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * Ilk is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public License
  14. * along with ilk. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <dirent.h>
  17. #include <inttypes.h>
  18. #include <rid.h>
  19. #include <stdint.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include <ctype.h>
  25. #define STYLE_9
  26. #include <fn85.h>
  27. #include <rid_fn85.h>
  28. #include <unfy/unfy.h>
  29. #include <unfy/unfp.h>
  30. #include <rls/rls.h>
  31. #include <rls/rlsp.h>
  32. #include <rls/rlsr.h>
  33. #define NIT_SHORT_NAMES
  34. #include <nit/list.h>
  35. #include <nit/set.h>
  36. #include <nit/map.h>
  37. #include <nit/err.h>
  38. #include <nit/file.h>
  39. #include <nit/buf.h>
  40. #include <nit/gap.h>
  41. #include <nit/crs.h>
  42. #include "../utilize.h"
  43. #include "../front.h"
  44. #include "acts.h"
  45. #define pass(str) (sizeof(str) - 1)
  46. typedef enum {
  47. ILK_NO_CMD,
  48. ILK_VIEW,
  49. ILK_SAVE,
  50. ILK_COUNT,
  51. ILK_RECALL,
  52. ILK_TEST,
  53. ILK_PROD,
  54. ILK_MODE,
  55. ILK_ACT,
  56. ILK_DEPS,
  57. } Ilk_cmd;
  58. void
  59. more_print(void *extra)
  60. {
  61. Ilk_more *more = extra;
  62. printf(".%" PRIu64, more->srch_cnt);
  63. }
  64. #define WORD_PARSE(LIT, ENUM_VAL) \
  65. if (!strncmp(str, LIT, pass(LIT))) { \
  66. *pos += pass(LIT); \
  67. return ENUM_VAL; \
  68. }
  69. Ilk_cmd
  70. ilk_cmd_parse(const char *str, size_t *pos)
  71. {
  72. switch (*str) {
  73. case 'a':
  74. WORD_PARSE("act", ILK_ACT);
  75. break;
  76. case 'v':
  77. WORD_PARSE("view", ILK_VIEW);
  78. break;
  79. case 's':
  80. WORD_PARSE("save", ILK_SAVE);
  81. break;
  82. case 'c':
  83. WORD_PARSE("count", ILK_COUNT);
  84. break;
  85. case 'r':
  86. WORD_PARSE("recall", ILK_RECALL);
  87. break;
  88. case 't':
  89. WORD_PARSE("test", ILK_TEST);
  90. break;
  91. case 'p':
  92. WORD_PARSE("prod", ILK_PROD);
  93. break;
  94. case 'm':
  95. WORD_PARSE("mode", ILK_MODE);
  96. break;
  97. case 'd':
  98. WORD_PARSE("deps", ILK_DEPS);
  99. break;
  100. }
  101. return ILK_NO_CMD;
  102. }
  103. void
  104. print_view(Ilk_sys *sys)
  105. {
  106. Nit_iter iter;
  107. if (!sys->grps.entry_num) {
  108. printf("Nothing here\n");
  109. return;
  110. }
  111. iter_init(&iter, &sys->grps);
  112. do {
  113. Ilk_grp *grp = iter_val(&iter);
  114. rlsp_rule_print(grp->rules, more_print);
  115. } while (iter_next(&iter));
  116. }
  117. static Unfy_stat
  118. ilk_recall(Ilk_sys *sys, char *str, size_t pos)
  119. {
  120. const char *error;
  121. uint64_t srch_cnt;
  122. Rls_srch *srch = NULL;
  123. if (unfp_space(str + pos, &pos, &error) < 0) {
  124. err_cust(&sys->lib->err, error);
  125. goto err_repl;
  126. }
  127. errno = 0;
  128. if (sscanf(str + pos, "%" PRIu64, &srch_cnt) < 1) {
  129. if (errno)
  130. err_std(&sys->lib->err);
  131. else if (str[pos] == '\0')
  132. err_cust(&sys->lib->err, "Missing digit");
  133. else
  134. err_cust(&sys->lib->err, "Invalid digit");
  135. goto err_repl;
  136. }
  137. if (ilk_srch_get(&srch, srch_cnt, sys) < 0)
  138. goto err_get;
  139. rlsp_srch_print(srch, 1);
  140. /* rls_recycle_srch(&sys->lib->rec, srch); */
  141. return UNFY_YES;
  142. err_repl:
  143. err_where(&sys->lib->err, "repl");
  144. err_pos(&sys->lib->err, pos);
  145. err_get:
  146. err_under(&sys->lib->err, pos + sizeof("* ") - 1);
  147. return UNFY_ERR;
  148. }
  149. static Ilk_act_num
  150. ilk_act_name(Ilk_sys *sys, char *str, size_t *pos)
  151. {
  152. const char *error;
  153. if (unfp_space(str + *pos, pos, &error) < 0) {
  154. err_cust(&sys->lib->err, error);
  155. goto err;
  156. }
  157. str += *pos;
  158. switch (*str) {
  159. case 'a':
  160. WORD_PARSE("add", ILK_ACT_ADD);
  161. break;
  162. case 'g':
  163. WORD_PARSE("gensym", ILK_ACT_GENSYM);
  164. break;
  165. }
  166. err_cust(&sys->lib->err, "Unknown act name");
  167. err:
  168. err_pos(&sys->lib->err, *pos);
  169. err_under(&sys->lib->err, *pos + sizeof("* ") - 1);
  170. err_where(&sys->lib->err, "repl");
  171. return ILK_ACT_NO;
  172. }
  173. static Unfy_stat
  174. repl_act(Ilk_sys *sys, char *str, size_t pos)
  175. {
  176. Ilk_act_num act = ilk_act_name(sys, str, &pos);
  177. Ilk_grp *grp;
  178. if (act == ILK_ACT_NO || !(grp = ilk_act_add2(sys, act)))
  179. return UNFY_ERR;
  180. return UNFY_YES;
  181. }
  182. static void
  183. deps_print(Nit_gap *deps)
  184. {
  185. Nit_crs crs;
  186. uint64_t srch_cnt;
  187. crs_init(&crs, deps, 0);
  188. while (crs_movef(&crs, sizeof(srch_cnt)) >= 0) {
  189. crs_read(&crs, &srch_cnt, sizeof(srch_cnt));
  190. srch_cnt = le64toh(srch_cnt);
  191. printf("%" PRIu64 " ", srch_cnt);
  192. }
  193. printf("\n");
  194. }
  195. static Unfy_stat
  196. repl_deps(Ilk_sys *sys, char *str, size_t pos)
  197. {
  198. size_t tmp;
  199. Rid id;
  200. const char *error;
  201. Ilk_meta meta;
  202. str += pos;
  203. tmp = pos;
  204. if (unfp_space(str, &pos, &error) < 0) {
  205. err_cust(&sys->lib->err, error);
  206. goto err_space;
  207. }
  208. str += pos - tmp;
  209. tmp = pos;
  210. if (rid_fn85_parse(id, str, &pos, &error) != FN85_OKAY)
  211. goto id_err;
  212. if (ilk_meta_load(&meta, id, sys) < 0)
  213. return UNFY_ERR;
  214. deps_print(&meta.deps);
  215. ilk_meta_dispose(&meta);
  216. return UNFY_YES;
  217. id_err:
  218. err_cust(&sys->lib->err, error);
  219. err_space:
  220. err_under(&sys->lib->err, pos + sizeof("* ") - 1);
  221. err_where(&sys->lib->err, "repl");
  222. err_pos(&sys->lib->err, pos);
  223. return UNFY_ERR;
  224. }
  225. static Unfy_stat
  226. ilk_lsn(Rlsr_lsnr *lsnr, Rls_rule **rules, Rls_srch **srch, char **str,
  227. size_t *size, Rls_info *info, void *extra, Rls_recycle *rec)
  228. {
  229. Ilk_sys *sys = extra;
  230. switch (ilk_cmd_parse(*str, &lsnr->pos)) {
  231. case ILK_SAVE:
  232. if (ilk_sys_save(sys) < 0)
  233. return UNFY_ERR;
  234. else
  235. printf("saved\n");
  236. return UNFY_YES;
  237. case ILK_VIEW:
  238. print_view(sys);
  239. return UNFY_YES;
  240. case ILK_COUNT:
  241. printf("%" PRIu64 "\n", sys->srch_cnt + 1);
  242. return UNFY_YES;
  243. case ILK_RECALL:
  244. return ilk_recall(sys, *str, lsnr->pos);
  245. case ILK_TEST:
  246. if (sys->lib->testing)
  247. printf("Already in testing mode\n");
  248. else
  249. printf("Changed to testing mode\n");
  250. sys->lib->testing = 1;
  251. return UNFY_YES;
  252. case ILK_PROD:
  253. if (!sys->lib->testing)
  254. printf("Already in production mode\n");
  255. else
  256. printf("Changed to production mode\n");
  257. sys->lib->testing = 0;
  258. return UNFY_YES;
  259. case ILK_MODE:
  260. if (sys->lib->testing)
  261. printf("In testing mode\n");
  262. else
  263. printf("In production mode\n");
  264. return UNFY_YES;
  265. case ILK_ACT:
  266. return repl_act(sys, *str, lsnr->pos);
  267. case ILK_DEPS:
  268. return repl_deps(sys, *str, lsnr->pos);
  269. case ILK_NO_CMD:
  270. break;
  271. }
  272. if (rlsr_default_lsn(lsnr, rules, srch, str,
  273. size, info, extra, rec) == UNFY_ERR) {
  274. if (!sys->lib->err.occured) {
  275. err_cust(&sys->lib->err, lsnr->error_str);
  276. err_pos(&sys->lib->err, lsnr->pos);
  277. err_under(&sys->lib->err, lsnr->pos + sizeof("* ") - 1);
  278. err_where(&sys->lib->err, "repl");
  279. }
  280. return UNFY_ERR;
  281. }
  282. return UNFY_YES;
  283. }
  284. static void
  285. handle_invalid_rule(Nit_err *err, Rlsr_stmnt *stmnt)
  286. {
  287. if (!ilk_rule_valid(stmnt->term, stmnt->list))
  288. return;
  289. err_where(err, "repl");
  290. err_pos(err, stmnt->term_pos);
  291. err_under(err, stmnt->term_pos + sizeof("* ") - 1);
  292. }
  293. int
  294. ilk_assert(Rlsr_lsnr *lsnr, Rlsr_stmnt *stmnt,
  295. Rls_rule **rules, void *extra, Rls_recycle *rec)
  296. {
  297. Ilk_sys *sys = extra;
  298. Ilk_grp *grp = ilk_rule_add(sys, stmnt->id, stmnt->term,
  299. stmnt->list, 0);
  300. if (!grp) {
  301. handle_invalid_rule(&sys->lib->err, stmnt);
  302. return -1;
  303. }
  304. *rules = grp->rules;
  305. return 0;
  306. }
  307. Unfy_stat
  308. ilk_search(Rlsr_lsnr *lsnr, Rlsr_stmnt *stmnt, Rls_srch **srch_ref,
  309. Rls_rule **rules, Rls_info *info, void *extra,
  310. Rls_recycle *rec)
  311. {
  312. Ilk_sys *sys = extra;
  313. Ilk_grp *grp = NULL;
  314. Unfy_stat stat;
  315. if (sys->lib->testing)
  316. stat = ilk_srch(sys, srch_ref, stmnt->term,
  317. &stmnt->limit, info);
  318. else
  319. stat = ilk_srch_n_save(sys, srch_ref, stmnt->term,
  320. &stmnt->limit, info);
  321. switch (stat) {
  322. case UNFY_NO:
  323. break;
  324. case UNFY_YES:
  325. /* This should never fail b/c search */
  326. grp = ilk_grp_get_term(sys, stmnt->term, &stat);
  327. break;
  328. case UNFY_ERR:
  329. handle_invalid_rule(&sys->lib->err, stmnt);
  330. break;
  331. }
  332. *rules = grp ? grp->rules : NULL;
  333. return stat;
  334. }
  335. void
  336. ilk_err(Rlsr_lsnr *lsnr, void *extra)
  337. {
  338. Ilk_sys *sys = extra;
  339. err_print(&sys->lib->err);
  340. sys->lib->err.occured = 0;
  341. }
  342. void
  343. ilk_repl(Ilk_sys *sys)
  344. {
  345. Rls_rule *rules = NULL;
  346. Rlsr_lsnr lsnr;
  347. rlsr_lsnr_init(&lsnr, ilk_lsn, ilk_assert, ilk_search,
  348. ilk_err, sys->lib->bend, NULL, 0);
  349. rlsr_repl(&rules, &lsnr, sys, &sys->lib->rec);
  350. if (!sys->lib->testing)
  351. ilk_sys_save(sys);
  352. }
  353. int
  354. main(int argc, char *argv[])
  355. {
  356. Ilk_lib lib;
  357. Ilk_sys *sys;
  358. ilk_lib_init(&lib, ILK_ACT_MAX, ilk_acts);
  359. if (!(sys = ilk_sys(&lib, "./"))) {
  360. err_print(&lib.err);
  361. return 0;
  362. }
  363. ilk_repl(sys);
  364. ilk_sys_rec(sys);
  365. ilk_lib_dispose(&lib);
  366. return 0;
  367. }