rlsp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. /* This file is part of rls.
  2. *
  3. * Rls 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. * Rls 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 rls. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <ctype.h>
  17. #include <endian.h>
  18. #include <inttypes.h>
  19. #include <rid.h>
  20. #include <stdint.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #define STYLE_9
  25. #include <fn85.h>
  26. #include <rid_fn85.h>
  27. #include <unfy/unfy.h>
  28. #include <unfy/unfp.h>
  29. #include "rls.h"
  30. #include "rlsp.h"
  31. /* length of constant size data for rule */
  32. static const size_t core_len = sizeof(Rid) + 2 * sizeof(uint16_t) +
  33. sizeof(uint8_t);
  34. static Rls_rule *
  35. get_rule(Rls_recycle *rec)
  36. {
  37. Rls_rule *rule = rec->rules;
  38. if (!rule)
  39. return malloc(sizeof(*rule));
  40. rec->rules = rule->next;
  41. return rule;
  42. }
  43. static Rls_srch *
  44. get_srch(Rls_recycle *rec)
  45. {
  46. Rls_srch *srch = rec->srchs;
  47. if (!srch)
  48. return malloc(sizeof(*srch));
  49. rec->srchs = (void *) srch->body;
  50. return srch;
  51. }
  52. /* rule */
  53. void
  54. rlsp_rule_print(const Rls_rule *rule, Rlsp_dat_print dat_print)
  55. {
  56. if (!rule) {
  57. printf("Empty\n");
  58. return;
  59. }
  60. for (; rule; rule = rule->next) {
  61. Rid_fn85 str;
  62. rid_fn85(str, rule->id);
  63. printf("%s", str);
  64. if (dat_print)
  65. dat_print(rule->dat);
  66. printf(" ");
  67. unfp_term_print(rule->head);
  68. printf(" ");
  69. if (rule->actable)
  70. printf("ACT");
  71. else
  72. unfp_list_print(rule->u.body);
  73. printf("\n");
  74. }
  75. }
  76. size_t
  77. rlsp_rule_len(const Rls_rule *rules, Rlsp_srlz *srlz, void *extra)
  78. {
  79. size_t len = 2;
  80. if (!rules)
  81. return 1;
  82. for (; rules; rules = rules->next) {
  83. len += 1 + core_len + unfp_term_len(rules->head);
  84. if (srlz)
  85. len += srlz->len(rules, extra);
  86. if (!rules->actable)
  87. len += unfp_list_len(rules->u.body);
  88. }
  89. return len;
  90. }
  91. size_t
  92. rlsp_rule_write(const Rls_rule *rules, unsigned char *buf,
  93. Rlsp_srlz *srlz, void *extra)
  94. {
  95. size_t len = 1;
  96. if (!rules) {
  97. *buf = RLSP_RNIL;
  98. return 1;
  99. }
  100. *buf = RLSP_ROPEN;
  101. for (; rules; rules = rules->next) {
  102. *(buf + len) = RLSP_RULE;
  103. ++len;
  104. rid_set(buf + len, rules->id);
  105. len += sizeof(rules->id);
  106. *(uint16_t *)(buf + len) = htole16(rules->size);
  107. len += sizeof(rules->size);
  108. *(uint16_t *)(buf + len) = htole16(rules->max_binds);
  109. len += sizeof(rules->max_binds);
  110. *(buf + len) = rules->actable;
  111. len += sizeof(rules->actable);
  112. len += unfp_term_write(rules->head, buf + len);
  113. if (srlz)
  114. len += srlz->write(rules, buf + len, extra);
  115. if (!rules->actable)
  116. len += unfp_list_write(rules->u.body, buf + len);
  117. }
  118. buf[len] = RLSP_RCLOSE;
  119. return len + 1;
  120. }
  121. int
  122. rlsp_rule_ser(const Rls_rule *rules, unsigned char **buf, size_t *size,
  123. size_t *pos, Rlsp_srlz *srlz, void *extra)
  124. {
  125. size_t len = rlsp_rule_len(rules, srlz, extra);
  126. if (*size < len) {
  127. unsigned char *new_buf = realloc(*buf, len);
  128. if (!new_buf)
  129. return -1;
  130. *buf = new_buf;
  131. *size = len;
  132. }
  133. rlsp_rule_write(rules, *buf, srlz, extra);
  134. *pos += len;
  135. return 0;
  136. }
  137. int
  138. rlsp_rule_deser(Rls_rule **rules, const unsigned char *buf, size_t *pos,
  139. Rlsp_srlz *srlz, void *extra, Rls_recycle *rec)
  140. {
  141. Rls_rule **end = rules;
  142. Rls_dat_free dat_free = srlz ? srlz->dat_free : NULL;
  143. *rules = NULL;
  144. if (*buf == RLSP_RNIL) {
  145. ++*pos;
  146. return 0;
  147. }
  148. if (*buf != RLSP_ROPEN)
  149. return -1;
  150. ++*pos;
  151. ++buf;
  152. do {
  153. size_t tmp = 1;
  154. if (*buf != RLSP_RULE || !(*end = get_rule(rec))) {
  155. rls_recycle_rule(rec, *rules, dat_free, extra);
  156. *rules = NULL;
  157. return -1;
  158. }
  159. (*end)->next = NULL;
  160. rid_set((*end)->id, buf + tmp);
  161. tmp += sizeof((*end)->id);
  162. (*end)->size = le16toh(*(uint16_t *)(buf + tmp));
  163. tmp += sizeof((*end)->size);
  164. (*end)->max_binds = le16toh(*(uint16_t *)(buf + tmp));
  165. tmp += sizeof((*end)->max_binds);
  166. (*end)->actable = *(buf + tmp);
  167. tmp += sizeof((*end)->actable);
  168. if (unfp_term_deser(&(*end)->head, buf + tmp,
  169. &tmp, &rec->unfy) < 0) {
  170. *pos += tmp;
  171. goto err;
  172. }
  173. *pos += tmp;
  174. buf += tmp;
  175. tmp = 0;
  176. if (srlz && srlz->deser(*end, buf, &tmp, extra) < 0)
  177. goto err;
  178. if (!(*end)->actable &&
  179. unfp_list_deser(&(*end)->u.body, buf + tmp,
  180. &tmp, &rec->unfy) < 0)
  181. goto err;
  182. *pos += tmp;
  183. buf += tmp;
  184. end = &(*end)->next;
  185. } while (*buf != RLSP_RCLOSE);
  186. ++*pos;
  187. return 0;
  188. err:
  189. /* This bit is a little hackish, basically makes this
  190. unfinished rule recyclable */
  191. (*end)->actable = 1;
  192. rls_recycle_rule(rec, *rules, dat_free, extra);
  193. *rules = NULL;
  194. return -1;
  195. }
  196. const char *
  197. rlsp_rule_deserable(const unsigned char *buf, size_t *pos,
  198. const size_t max, Rlsp_srlz *srlz, void *extra)
  199. {
  200. const char *error;
  201. if (!buf || *pos >= max)
  202. return "Not enough space for rule";
  203. switch (*buf) {
  204. case RLSP_RNIL:
  205. ++*pos;
  206. return NULL;
  207. case RLSP_ROPEN:
  208. break;
  209. default:
  210. return "Missing rule byte";
  211. }
  212. ++*pos;
  213. ++buf;
  214. do {
  215. size_t tmp = 0;
  216. uint8_t actable;
  217. if (*buf != RLSP_RULE)
  218. return "Missing rule byte";
  219. ++*pos;
  220. ++buf;
  221. if (*pos + core_len > max) {
  222. *pos = max;
  223. return "Content of rule exceeds maximum";
  224. }
  225. tmp = (*pos += core_len);
  226. buf += core_len;
  227. actable = buf[-1];
  228. if ((error = unfp_term_deserable(buf, pos, max)))
  229. return error;
  230. buf += *pos - tmp;
  231. tmp = *pos;
  232. if (srlz && (error = srlz->deserable(buf, pos, max, extra)))
  233. return error;
  234. buf += *pos - tmp;
  235. tmp = *pos;
  236. if (!actable && (error = unfp_list_deserable(buf, pos, max)))
  237. return error;
  238. buf += *pos - tmp;
  239. if (*pos + 1 > max)
  240. return "Missing rule close byte";
  241. } while (*buf != RLSP_RCLOSE);
  242. ++*pos;
  243. return NULL;
  244. }
  245. /* srch */
  246. static void
  247. indent_level(int level)
  248. {
  249. for (int i = 0; i < level; ++i)
  250. printf("\t");
  251. }
  252. static void
  253. binds_flow_print(const Rls_srch *srch, int level)
  254. {
  255. Unfy_bind *bind = srch->nbind;
  256. indent_level(level);
  257. printf("Left\n");
  258. for (; bind; bind = bind->next) {
  259. Unfy_term *lterm = unfy_bind_get(srch->lbind, bind->term->u.id);
  260. Unfy_term *fterm = unfy_bind_get(srch->fbind, bind->var_id);
  261. indent_level(level + 1);
  262. unfp_bind_print(bind);
  263. if (lterm) {
  264. printf(" -> ");
  265. unfp_term_print(lterm);
  266. }
  267. if (fterm) {
  268. printf(" -> ");
  269. unfp_term_print(fterm);
  270. }
  271. printf("\n");
  272. }
  273. indent_level(level);
  274. printf("RIGHT\n");
  275. unfp_binds_print(srch->rbind, level + 1);
  276. }
  277. void
  278. rlsp_srch_print(const Rls_srch *srch, int level)
  279. {
  280. for (int i = 0; i < level; ++i)
  281. printf("\t");
  282. if (!srch) {
  283. printf("Empty\n");
  284. return;
  285. }
  286. printf("%" PRIu16 ".", srch->num);
  287. unfp_term_print(srch->term);
  288. printf("\n");
  289. binds_flow_print(srch, level + 1);
  290. if (!srch->rule->actable && srch->body)
  291. for (int i = 0; i < srch->rule->size; ++i)
  292. rlsp_srch_print(srch->body[i], level + 1);
  293. }
  294. size_t
  295. rlsp_srch_len(const Rls_srch *srch)
  296. {
  297. size_t len = 1 + sizeof(srch->rule->id) + sizeof(srch->num) +
  298. sizeof(srch->rule->size);
  299. if (!srch)
  300. return 1;
  301. len += unfp_term_len(srch->term) + unfp_bind_len(srch->lbind) +
  302. unfp_bind_len(srch->rbind) + unfp_bind_len(srch->nbind) +
  303. unfp_bind_len(srch->fbind);
  304. for (int i = 0; i < srch->rule->size; ++i)
  305. len += rlsp_srch_len(srch->body[i]);
  306. return len;
  307. }
  308. size_t
  309. rlsp_srch_write(const Rls_srch *srch, unsigned char *buf)
  310. {
  311. size_t len = 1;
  312. if (!srch) {
  313. *buf = RLSP_SNIL;
  314. return 1;
  315. }
  316. *buf = RLSP_SOPEN;
  317. rid_set(buf + len, srch->rule->id);
  318. len += sizeof(Rid);
  319. *(uint16_t *)(buf + len) = htole16(srch->num);
  320. len += sizeof(srch->num);
  321. *(uint16_t *)(buf + len) = htole16(srch->rule->size);
  322. len += sizeof(srch->rule->size);
  323. len += unfp_term_write(srch->term, buf + len);
  324. len += unfp_bind_write(srch->lbind, buf + len);
  325. len += unfp_bind_write(srch->rbind, buf + len);
  326. len += unfp_bind_write(srch->nbind, buf + len);
  327. len += unfp_bind_write(srch->fbind, buf + len);
  328. for (int i = 0; i < srch->rule->size; ++i)
  329. len += rlsp_srch_write(srch->body[i], buf + len);
  330. return len;
  331. }
  332. int
  333. rlsp_srch_ser(const Rls_srch *srch, unsigned char **buf,
  334. size_t *size, size_t *pos)
  335. {
  336. size_t len = rlsp_srch_len(srch);
  337. if (*size < len) {
  338. unsigned char *new_buf = realloc(*buf, len);
  339. if (!new_buf)
  340. return -1;
  341. *buf = new_buf;
  342. *size = len;
  343. }
  344. rlsp_srch_write(srch, *buf);
  345. *pos += len;
  346. return 0;
  347. }
  348. const char *
  349. rlsp_srch_deser(Rls_srch **srch, const unsigned char *buf, size_t *pos,
  350. Rls_rule *rules, Rls_bend bend, void *extra, Rls_recycle *rec)
  351. {
  352. size_t len;
  353. Rid rule_id;
  354. uint16_t num;
  355. uint16_t size;
  356. Rls_rule *rule = rules;
  357. Unfy_term *term;
  358. const char *error;
  359. if (*buf == RLSP_SNIL) {
  360. *srch = NULL;
  361. ++*pos;
  362. return NULL;
  363. }
  364. if (*buf != RLSP_SOPEN) {
  365. *srch = NULL;
  366. return "Missing srch byte";
  367. }
  368. len = 1;
  369. rid_set(rule_id, buf + len);
  370. len += sizeof(rule_id);
  371. num = le16toh(*(uint16_t *)(buf + len));
  372. len += sizeof(num);
  373. size = le16toh(*(uint16_t *)(buf + len));
  374. len += sizeof(size);
  375. if (unfp_term_deser(&term, buf + len, &len, &rec->unfy) < 0)
  376. return "Failed to deser term";
  377. if (bend) {
  378. Unfy_stat stat = UNFY_ERR;
  379. Rls_rule **tmp = bend(term, &stat, extra);
  380. if (!tmp) {
  381. /* we can't find the rule, so we can't deser */
  382. unfy_recycle_term(&rec->unfy, term);
  383. return "Failed rule bend";
  384. }
  385. rule = *tmp;
  386. }
  387. for (; rule && rid_cmp(rule->id, rule_id); rule = rule->next);
  388. if (!rule) {
  389. unfy_recycle_term(&rec->unfy, term);
  390. return "Rule not found";
  391. }
  392. if (!(*srch = get_srch(rec))) {
  393. unfy_recycle_term(&rec->unfy, term);
  394. return "Failed to allocate srch";
  395. }
  396. (*srch)->up = NULL;
  397. (*srch)->rule = rule;
  398. (*srch)->term = term;
  399. (*srch)->num = num;
  400. if (!size)
  401. (*srch)->body = NULL;
  402. else if (!((*srch)->body = calloc(size, sizeof(Rls_srch *)))) {
  403. error = "Failed to allocate body";
  404. goto body_err;
  405. }
  406. if (unfp_bind_deser(&(*srch)->lbind, buf + len, &len, &rec->unfy) < 0) {
  407. error = "Failed to deser lbind";
  408. goto lbind_err;
  409. }
  410. if (unfp_bind_deser(&(*srch)->rbind, buf + len, &len, &rec->unfy) < 0) {
  411. error = "Failed to deser rbind";
  412. goto rbind_err;
  413. }
  414. if (unfp_bind_deser(&(*srch)->nbind, buf + len, &len, &rec->unfy) < 0) {
  415. error = "Failed to deser nbind";
  416. goto nbind_err;
  417. }
  418. if (unfp_bind_deser(&(*srch)->fbind, buf + len, &len, &rec->unfy) < 0) {
  419. error = "Failed to deser fbind";
  420. goto full_err;
  421. }
  422. for (int i = 0; i < size; ++i) {
  423. if ((error = rlsp_srch_deser(&(*srch)->body[i], buf + len,
  424. &len, rules, bend, extra, rec)))
  425. goto full_err;
  426. (*srch)->body[i]->up = *srch;
  427. }
  428. *pos += len;
  429. return NULL;
  430. body_err:
  431. (*srch)->lbind = NULL;
  432. lbind_err:
  433. (*srch)->rbind = NULL;
  434. rbind_err:
  435. (*srch)->nbind = NULL;
  436. nbind_err:
  437. (*srch)->fbind = NULL;
  438. full_err:
  439. rls_recycle_srch(rec, *srch);
  440. *srch = NULL;
  441. return error;
  442. }
  443. const char *
  444. rlsp_srch_deserable(const unsigned char *buf, size_t *pos, const size_t max)
  445. {
  446. const char *error;
  447. uint16_t size;
  448. size_t tmp;
  449. if (!buf || *pos >= max)
  450. return "Not enough space for srch";
  451. switch (*buf) {
  452. case RLSP_SNIL:
  453. ++*pos;
  454. return NULL;
  455. case RLSP_SOPEN:
  456. break;
  457. default:
  458. return "Missing srch byte";
  459. }
  460. ++*pos;
  461. ++buf;
  462. if (*pos + sizeof(Rid) + 2 * sizeof(uint16_t) > max) {
  463. *pos = max;
  464. return NULL;
  465. }
  466. *pos += sizeof(Rid) + 2 * sizeof(uint16_t);
  467. buf += sizeof(Rid) + 2 * sizeof(uint16_t);
  468. size = ((uint16_t *) buf)[-1];
  469. tmp = *pos;
  470. if ((error = unfp_term_deserable(buf, pos, max)))
  471. return error;
  472. for (int i = 0; i < 4; ++i) {
  473. buf += *pos - tmp;
  474. tmp = *pos;
  475. if ((error = unfp_bind_deserable(buf, pos, max)))
  476. return error;
  477. }
  478. for (uint16_t i = 0; i < size; ++i) {
  479. buf += *pos - tmp;
  480. tmp = *pos;
  481. if ((error = rlsp_srch_deserable(buf, pos, max)))
  482. return error;
  483. }
  484. return NULL;
  485. }