unfp.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /* This file is part of unfy.
  2. *
  3. * Unfy 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. * Unfy 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 unfy. If not, see <http://www.gnu.org/licenses/>.
  15. */
  16. #include <ctype.h>
  17. #include <endian.h>
  18. #include <rid.h>
  19. #include <stdint.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #define STYLE_9
  24. #include <fn85.h>
  25. #include <rid_fn85.h>
  26. #include "unfy.h"
  27. #include "unfp.h"
  28. #define pass(str) (sizeof(str) - 1)
  29. /* term */
  30. void
  31. unfp_term_print(const Unfy_term *term)
  32. {
  33. Rid_fn85 str;
  34. if (!term) {
  35. printf("EMPTY");
  36. return;
  37. }
  38. switch (term->type) {
  39. case UNFY_CONST:
  40. printf("const ");
  41. break;
  42. case UNFY_ORDER:
  43. printf("order %zu", term->u.order);
  44. return;
  45. case UNFY_IGN:
  46. printf("_");
  47. return;
  48. case UNFY_LIST:
  49. unfp_list_print(term->u.list);
  50. return;
  51. case UNFY_VAR:
  52. printf("var ");
  53. break;
  54. }
  55. rid_fn85(str, term->u.id);
  56. printf("%s", str);
  57. }
  58. Unfy_term *
  59. unfp_term_parse(const char *str, size_t *pos,
  60. const char **error, Unfy_recycle *rec)
  61. {
  62. Unfy_type type;
  63. Rid id;
  64. Unfy_term *term;
  65. Unfy_list *list;
  66. size_t order;
  67. size_t tmp;
  68. int scanf_pos = 0;
  69. switch (*str) {
  70. case 'c':
  71. if (strncmp(str, "const", pass("const"))) {
  72. *error = "Invalid type";
  73. return NULL;
  74. }
  75. *pos += pass("const");
  76. str += pass("const");
  77. type = UNFY_CONST;
  78. break;
  79. case 'o':
  80. if (strncmp(str, "order", pass("order"))) {
  81. *error = "Invalid type";
  82. return NULL;
  83. }
  84. *pos += pass("order");
  85. str += pass("order");
  86. tmp = *pos;
  87. if (unfp_space(str, pos, error) < 0)
  88. return NULL;
  89. str += *pos - tmp;
  90. if (1 != sscanf(str, "%zu%n", &order, &scanf_pos)) {
  91. *pos += scanf_pos;
  92. *error = "invalid digit for order";
  93. return NULL;
  94. }
  95. *pos += scanf_pos;
  96. if (!(term = unfy_term(UNFY_ORDER, &order, rec)))
  97. *error = "Failed to allocate term";
  98. return term;
  99. case '_':
  100. *pos += 1;
  101. if (!(term = unfy_term(UNFY_IGN, NULL, rec)))
  102. *error = "Failed to allocate term";
  103. return term;
  104. case '(':
  105. if (unfp_list_parse(&list, str, pos, error, rec) < 0)
  106. return NULL;
  107. if (!(term = unfy_term(UNFY_LIST, list, rec))) {
  108. *error = "Failed to allocate term";
  109. unfy_recycle_list(rec, list);
  110. return NULL;
  111. }
  112. return term;
  113. case 'v':
  114. if (strncmp(str, "var", pass("var"))) {
  115. *error = "Invalid type";
  116. return NULL;
  117. }
  118. *pos += pass("var");
  119. str += pass("var");
  120. type = UNFY_VAR;
  121. break;
  122. default:
  123. *error = "Invalid type";
  124. return NULL;
  125. }
  126. tmp = *pos;
  127. if (unfp_space(str, pos, error) < 0)
  128. return NULL;
  129. str += *pos - tmp;
  130. if (rid_fn85_parse(id, str, pos, error) != FN85_OKAY)
  131. return NULL;
  132. term = unfy_term(type, id, rec);
  133. if (!term)
  134. *error = "Failed to allocate term";
  135. return term;
  136. }
  137. size_t
  138. unfp_term_len(const Unfy_term *term)
  139. {
  140. if (!term)
  141. return 1;
  142. switch (term->type) {
  143. case UNFY_CONST:
  144. case UNFY_VAR:
  145. return sizeof(Rid) + 1;
  146. case UNFY_ORDER:
  147. return sizeof(uint64_t) + 1;
  148. case UNFY_IGN:
  149. return 1;
  150. case UNFY_LIST:
  151. return unfp_list_len(term->u.list);
  152. }
  153. return 0;
  154. }
  155. size_t
  156. unfp_term_write(const Unfy_term *term, unsigned char *buf)
  157. {
  158. if (!term) {
  159. *buf = UNFP_TNIL;
  160. return 1;
  161. }
  162. switch (term->type) {
  163. case UNFY_CONST:
  164. *buf = UNFP_CONST;
  165. rid_set(buf + 1, term->u.id);
  166. return sizeof(Rid) + 1;
  167. case UNFY_ORDER:
  168. *buf = UNFP_ORDER;
  169. *(uint64_t *) (buf + 1) = htole64(term->u.order);
  170. return sizeof(uint64_t) + 1;
  171. case UNFY_IGN:
  172. *buf = UNFP_IGN;
  173. return 1;
  174. case UNFY_VAR:
  175. *buf = UNFP_VAR;
  176. rid_set(buf + 1, term->u.id);
  177. return sizeof(Rid) + 1;
  178. case UNFY_LIST:
  179. return unfp_list_write(term->u.list, buf);
  180. }
  181. return 0;
  182. }
  183. int
  184. unfp_term_ser(const Unfy_term *term, unsigned char **buf,
  185. size_t *size, size_t *pos)
  186. {
  187. size_t len = unfp_term_len(term);
  188. if (*size < len) {
  189. unsigned char *new_buf = realloc(*buf, len);
  190. if (!new_buf)
  191. return -1;
  192. *buf = new_buf;
  193. *size = len;
  194. }
  195. unfp_term_write(term, *buf);
  196. *pos += len;
  197. return 0;
  198. }
  199. int
  200. unfp_term_deser(Unfy_term **term, const unsigned char *buf,
  201. size_t *pos, Unfy_recycle *rec)
  202. {
  203. Unfy_list *list;
  204. size_t order;
  205. switch (*buf) {
  206. case UNFP_TNIL:
  207. ++*pos;
  208. *term = NULL;
  209. return 0;
  210. case UNFP_CONST:
  211. *pos += sizeof(Rid) + 1;
  212. *term = unfy_term_id(UNFY_CONST, buf + 1, rec);
  213. return *term ? 0 : -1;
  214. case UNFP_ORDER:
  215. *pos += sizeof(uint64_t) + 1;
  216. order = le64toh(*(uint64_t *) (buf + 1));
  217. *term = unfy_term(UNFY_ORDER, &order, rec);
  218. return *term ? 0 : -1;
  219. case UNFP_IGN:
  220. ++*pos;
  221. *term = unfy_term(UNFY_IGN, NULL, rec);
  222. return *term ? 0 : -1;
  223. case UNFP_VAR:
  224. *pos += sizeof(Rid) + 1;
  225. *term = unfy_term_id(UNFY_VAR, buf + 1, rec);
  226. return *term ? 0 : -1;
  227. case UNFP_LOPEN:
  228. case UNFP_LNIL:
  229. break;
  230. default:
  231. return -1;
  232. }
  233. if (unfp_list_deser(&list, buf, pos, rec) < 0)
  234. return -1;
  235. if (!(*term = unfy_term(UNFY_LIST, list, rec))) {
  236. unfy_recycle_list(rec, list);
  237. return -1;
  238. }
  239. return 0;
  240. }
  241. const char *
  242. unfp_term_deserable(const unsigned char *buf, size_t *pos, const size_t max)
  243. {
  244. if (!buf || *pos >= max)
  245. return "Not enough space for term";
  246. switch (*buf) {
  247. case UNFP_TNIL:
  248. case UNFP_IGN:
  249. ++*pos;
  250. return NULL;
  251. case UNFP_CONST:
  252. case UNFP_VAR:
  253. if (*pos + sizeof(Rid) + 1 > max) {
  254. *pos = max;
  255. return "Not enough space for id";
  256. }
  257. *pos += sizeof(Rid) + 1;
  258. return NULL;
  259. case UNFP_ORDER:
  260. if (*pos + sizeof(uint64_t) + 1 > max) {
  261. *pos = max;
  262. return "Not enough space for order";
  263. }
  264. *pos += sizeof(uint64_t) + 1;
  265. return NULL;
  266. case UNFP_LNIL:
  267. case UNFP_LOPEN:
  268. return unfp_list_deserable(buf, pos, max);
  269. default:
  270. break;
  271. }
  272. return "Not a valid term type";
  273. }
  274. /* list */
  275. void
  276. unfp_list_print(const Unfy_list *list)
  277. {
  278. printf("(");
  279. if (!list) {
  280. printf(")");
  281. return;
  282. }
  283. unfp_term_print(list->term);
  284. list = list->next;
  285. for (; list; list = list->next) {
  286. printf(" ");
  287. unfp_term_print(list->term);
  288. }
  289. printf(")");
  290. }
  291. int
  292. unfp_list_parse(Unfy_list **list, const char *str, size_t *pos,
  293. const char **error, Unfy_recycle *rec)
  294. {
  295. int first = 1;
  296. Unfy_list **tail = list;
  297. *list = NULL;
  298. if (*str != '(') {
  299. *error = "No bracket at start of list";
  300. return -1;
  301. }
  302. ++*pos;
  303. ++str;
  304. for (; isspace(*str); ++*pos, ++str);
  305. while (*str != ')') {
  306. size_t old = *pos;
  307. Unfy_term *term;
  308. if (!first) {
  309. if (unfp_space(str, pos, error) < 0)
  310. return -1;
  311. if (*(str += *pos - old) == ')')
  312. break;
  313. } else {
  314. first = 0;
  315. }
  316. old = *pos;
  317. if (!(term = unfp_term_parse(str, pos, error, rec))) {
  318. unfy_recycle_list(rec, *list);
  319. return -1;
  320. }
  321. str += *pos - old;
  322. if (!(tail = unfy_list_append(tail, term, rec))) {
  323. *error = "Failed to append to list";
  324. unfy_recycle_term(rec, term);
  325. unfy_recycle_list(rec, *list);
  326. return -1;
  327. }
  328. }
  329. ++*pos;
  330. return 0;
  331. }
  332. size_t
  333. unfp_list_len(const Unfy_list *list)
  334. {
  335. size_t len = 2;
  336. if (!list)
  337. return 1;
  338. for (; list; list = list->next)
  339. len += unfp_term_len(list->term);
  340. return len;
  341. }
  342. size_t
  343. unfp_list_write(const Unfy_list *list, unsigned char *buf)
  344. {
  345. int len = 1;
  346. if (!list) {
  347. *buf = UNFP_LNIL;
  348. return 1;
  349. }
  350. *buf = UNFP_LOPEN;
  351. for (; list; list = list->next)
  352. len += unfp_term_write(list->term, buf + len);
  353. buf[len] = UNFP_LCLOSE;
  354. return len + 1;
  355. }
  356. int
  357. unfp_list_ser(const Unfy_list *list, unsigned char **buf,
  358. size_t *size, size_t *pos)
  359. {
  360. size_t len = unfp_list_len(list);
  361. if (*size < len) {
  362. unsigned char *new_buf = realloc(*buf, len);
  363. if (!new_buf)
  364. return -1;
  365. *buf = new_buf;
  366. *size = len;
  367. }
  368. unfp_list_write(list, *buf);
  369. *pos += len;
  370. return 0;
  371. }
  372. int
  373. unfp_list_deser(Unfy_list **list, const unsigned char *buf,
  374. size_t *pos, Unfy_recycle *rec)
  375. {
  376. Unfy_list **end = list;
  377. *list = NULL;
  378. if (*buf == UNFP_LNIL) {
  379. ++*pos;
  380. return 0;
  381. }
  382. if (*buf != UNFP_LOPEN)
  383. return -1;
  384. ++*pos;
  385. ++buf;
  386. do {
  387. Unfy_term *term;
  388. size_t tmp = 0;
  389. if (unfp_term_deser(&term, buf, &tmp, rec) < 0) {
  390. unfy_recycle_list(rec, *list);
  391. return -1;
  392. }
  393. if (!(end = unfy_list_append(end, term, rec))) {
  394. unfy_recycle_term(rec, term);
  395. unfy_recycle_list(rec, *list);
  396. return -1;
  397. }
  398. *pos += tmp;
  399. buf += tmp;
  400. } while (*buf != UNFP_LCLOSE);
  401. ++*pos;
  402. return 0;
  403. }
  404. const char *
  405. unfp_list_deserable(const unsigned char *buf, size_t *pos, const size_t max)
  406. {
  407. const char *error;
  408. if (!buf || *pos >= max)
  409. return "Not enough space for list";
  410. switch (*buf) {
  411. case UNFP_LNIL:
  412. ++*pos;
  413. return NULL;
  414. case UNFP_LOPEN:
  415. break;
  416. default:
  417. return "Missing list byte";
  418. }
  419. ++*pos;
  420. ++buf;
  421. do {
  422. size_t tmp = *pos;
  423. if ((error = unfp_term_deserable(buf, pos, max)))
  424. return error;
  425. if (*pos + 1 > max) {
  426. *pos = max;
  427. return "Missing list close byte";
  428. }
  429. buf += *pos - tmp;
  430. } while (*buf != UNFP_LCLOSE);
  431. ++*pos;
  432. return NULL;
  433. }
  434. /* bind */
  435. void
  436. unfp_bind_print(const Unfy_bind *bind)
  437. {
  438. Rid_fn85 str;
  439. if (!bind) {
  440. printf("EMPTY");
  441. return;
  442. }
  443. rid_fn85(str, bind->var_id);
  444. printf("var %s -> ", str);
  445. unfp_term_print(bind->term);
  446. }
  447. void
  448. unfp_binds_print(const Unfy_bind *bind, int level)
  449. {
  450. if (!bind) {
  451. for (int i = 0; i < level; ++i)
  452. printf("\t");
  453. printf("EMPTY\n");
  454. return;
  455. }
  456. for (; bind; bind = bind->next) {
  457. for (int i = 0; i < level; ++i)
  458. printf("\t");
  459. unfp_bind_print(bind);
  460. printf("\n");
  461. }
  462. }
  463. int
  464. unfp_space(const char *str, size_t *pos, const char **error)
  465. {
  466. if (!isspace(*str)) {
  467. *error = "Missing a space";
  468. return -1;
  469. }
  470. ++str;
  471. ++*pos;
  472. for (; isspace(*str); ++str, ++*pos);
  473. return 0;
  474. }
  475. size_t
  476. unfp_bind_len(const Unfy_bind *bind)
  477. {
  478. size_t len = 2;
  479. if (!bind)
  480. return 1;
  481. for (; bind; bind = bind->next)
  482. len += unfp_term_len(bind->term) + sizeof(bind->var_id);
  483. return len;
  484. }
  485. size_t
  486. unfp_bind_write(const Unfy_bind *bind, unsigned char *buf)
  487. {
  488. int len = 1;
  489. if (!bind) {
  490. *buf = UNFP_BNIL;
  491. return 1;
  492. }
  493. *buf = UNFP_BOPEN;
  494. for (; bind; bind = bind->next) {
  495. len += unfp_term_write(bind->term, buf + len);
  496. rid_set(buf + len, bind->var_id);
  497. len += sizeof(bind->var_id);
  498. }
  499. buf[len] = UNFP_BCLOSE;
  500. return len + 1;
  501. }
  502. int
  503. unfp_bind_ser(const Unfy_bind *bind, unsigned char **buf,
  504. size_t *size, size_t *pos)
  505. {
  506. size_t len = unfp_bind_len(bind);
  507. if (*size < len) {
  508. unsigned char *new_buf = realloc(*buf, len);
  509. if (!new_buf)
  510. return -1;
  511. *buf = new_buf;
  512. *size = len;
  513. }
  514. unfp_bind_write(bind, *buf);
  515. *pos += len;
  516. return 0;
  517. }
  518. int
  519. unfp_bind_deser(Unfy_bind **bind, const unsigned char *buf,
  520. size_t *pos, Unfy_recycle *rec)
  521. {
  522. Unfy_bind **end = bind;
  523. *bind = NULL;
  524. if (*buf == UNFP_BNIL) {
  525. ++*pos;
  526. return 0;
  527. }
  528. if (*buf != UNFP_BOPEN)
  529. return -1;
  530. ++*pos;
  531. ++buf;
  532. do {
  533. Unfy_term *term;
  534. size_t tmp = 0;
  535. Rid var_id;
  536. if (unfp_term_deser(&term, buf, &tmp, rec) < 0) {
  537. unfy_recycle_bind(rec, *bind);
  538. return -1;
  539. }
  540. rid_set(var_id, buf + tmp);
  541. tmp += sizeof(var_id);
  542. if (unfy_bind(end, var_id, term, rec) < 0) {
  543. unfy_recycle_term(rec, term);
  544. unfy_recycle_bind(rec, *bind);
  545. return -1;
  546. }
  547. *pos += tmp;
  548. buf += tmp;
  549. *(end = &(*end)->next) = NULL;
  550. } while (*buf != UNFP_BCLOSE);
  551. ++*pos;
  552. return 0;
  553. }
  554. const char *
  555. unfp_bind_deserable(const unsigned char *buf, size_t *pos, const size_t max)
  556. {
  557. const char *error;
  558. if (!buf || *pos >= max)
  559. return "Not enough space for bind";
  560. switch (*buf) {
  561. case UNFP_BNIL:
  562. ++*pos;
  563. return NULL;
  564. case UNFP_BOPEN:
  565. break;
  566. default:
  567. return "Missing bind byte";
  568. }
  569. ++*pos;
  570. ++buf;
  571. do {
  572. size_t tmp = *pos;
  573. if ((error = unfp_term_deserable(buf, pos, max)))
  574. return error;
  575. if (*pos + sizeof(Rid) + 1 > max) {
  576. *pos = max;
  577. return "Content of bind exceeds maximum";
  578. }
  579. *pos += sizeof(Rid);
  580. buf += *pos - tmp;
  581. } while (*buf != UNFP_BCLOSE);
  582. ++*pos;
  583. return NULL;
  584. }