123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737 |
- /* This file is part of unfy.
- *
- * Unfy is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Unfy is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with unfy. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <ctype.h>
- #include <endian.h>
- #include <rid.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define STYLE_9
- #include <fn85.h>
- #include <rid_fn85.h>
- #include "unfy.h"
- #include "unfp.h"
- #define pass(str) (sizeof(str) - 1)
- /* term */
- void
- unfp_term_print(const Unfy_term *term)
- {
- Rid_fn85 str;
- if (!term) {
- printf("EMPTY");
- return;
- }
- switch (term->type) {
- case UNFY_CONST:
- printf("const ");
- break;
- case UNFY_ORDER:
- printf("order %zu", term->u.order);
- return;
- case UNFY_IGN:
- printf("_");
- return;
- case UNFY_LIST:
- unfp_list_print(term->u.list);
- return;
- case UNFY_VAR:
- printf("var ");
- break;
- }
- rid_fn85(str, term->u.id);
- printf("%s", str);
- }
- Unfy_term *
- unfp_term_parse(const char *str, size_t *pos,
- const char **error, Unfy_recycle *rec)
- {
- Unfy_type type;
- Rid id;
- Unfy_term *term;
- Unfy_list *list;
- size_t order;
- size_t tmp;
- int scanf_pos = 0;
- switch (*str) {
- case 'c':
- if (strncmp(str, "const", pass("const"))) {
- *error = "Invalid type";
- return NULL;
- }
- *pos += pass("const");
- str += pass("const");
- type = UNFY_CONST;
- break;
- case 'o':
- if (strncmp(str, "order", pass("order"))) {
- *error = "Invalid type";
- return NULL;
- }
- *pos += pass("order");
- str += pass("order");
- tmp = *pos;
- if (unfp_space(str, pos, error) < 0)
- return NULL;
- str += *pos - tmp;
- if (1 != sscanf(str, "%zu%n", &order, &scanf_pos)) {
- *pos += scanf_pos;
- *error = "invalid digit for order";
- return NULL;
- }
- *pos += scanf_pos;
- if (!(term = unfy_term(UNFY_ORDER, &order, rec)))
- *error = "Failed to allocate term";
- return term;
- case '_':
- *pos += 1;
- if (!(term = unfy_term(UNFY_IGN, NULL, rec)))
- *error = "Failed to allocate term";
- return term;
- case '(':
- if (unfp_list_parse(&list, str, pos, error, rec) < 0)
- return NULL;
- if (!(term = unfy_term(UNFY_LIST, list, rec))) {
- *error = "Failed to allocate term";
- unfy_recycle_list(rec, list);
- return NULL;
- }
- return term;
- case 'v':
- if (strncmp(str, "var", pass("var"))) {
- *error = "Invalid type";
- return NULL;
- }
- *pos += pass("var");
- str += pass("var");
- type = UNFY_VAR;
- break;
- default:
- *error = "Invalid type";
- return NULL;
- }
- tmp = *pos;
- if (unfp_space(str, pos, error) < 0)
- return NULL;
- str += *pos - tmp;
- if (rid_fn85_parse(id, str, pos, error) != FN85_OKAY)
- return NULL;
- term = unfy_term(type, id, rec);
- if (!term)
- *error = "Failed to allocate term";
- return term;
- }
- size_t
- unfp_term_len(const Unfy_term *term)
- {
- if (!term)
- return 1;
- switch (term->type) {
- case UNFY_CONST:
- case UNFY_VAR:
- return sizeof(Rid) + 1;
- case UNFY_ORDER:
- return sizeof(uint64_t) + 1;
- case UNFY_IGN:
- return 1;
- case UNFY_LIST:
- return unfp_list_len(term->u.list);
- }
- return 0;
- }
- size_t
- unfp_term_write(const Unfy_term *term, unsigned char *buf)
- {
- if (!term) {
- *buf = UNFP_TNIL;
- return 1;
- }
- switch (term->type) {
- case UNFY_CONST:
- *buf = UNFP_CONST;
- rid_set(buf + 1, term->u.id);
- return sizeof(Rid) + 1;
- case UNFY_ORDER:
- *buf = UNFP_ORDER;
- *(uint64_t *) (buf + 1) = htole64(term->u.order);
- return sizeof(uint64_t) + 1;
- case UNFY_IGN:
- *buf = UNFP_IGN;
- return 1;
- case UNFY_VAR:
- *buf = UNFP_VAR;
- rid_set(buf + 1, term->u.id);
- return sizeof(Rid) + 1;
- case UNFY_LIST:
- return unfp_list_write(term->u.list, buf);
- }
- return 0;
- }
- int
- unfp_term_ser(const Unfy_term *term, unsigned char **buf,
- size_t *size, size_t *pos)
- {
- size_t len = unfp_term_len(term);
- if (*size < len) {
- unsigned char *new_buf = realloc(*buf, len);
- if (!new_buf)
- return -1;
- *buf = new_buf;
- *size = len;
- }
- unfp_term_write(term, *buf);
- *pos += len;
- return 0;
- }
- int
- unfp_term_deser(Unfy_term **term, const unsigned char *buf,
- size_t *pos, Unfy_recycle *rec)
- {
- Unfy_list *list;
- size_t order;
- switch (*buf) {
- case UNFP_TNIL:
- ++*pos;
- *term = NULL;
- return 0;
- case UNFP_CONST:
- *pos += sizeof(Rid) + 1;
- *term = unfy_term_id(UNFY_CONST, buf + 1, rec);
- return *term ? 0 : -1;
- case UNFP_ORDER:
- *pos += sizeof(uint64_t) + 1;
- order = le64toh(*(uint64_t *) (buf + 1));
- *term = unfy_term(UNFY_ORDER, &order, rec);
- return *term ? 0 : -1;
- case UNFP_IGN:
- ++*pos;
- *term = unfy_term(UNFY_IGN, NULL, rec);
- return *term ? 0 : -1;
- case UNFP_VAR:
- *pos += sizeof(Rid) + 1;
- *term = unfy_term_id(UNFY_VAR, buf + 1, rec);
- return *term ? 0 : -1;
- case UNFP_LOPEN:
- case UNFP_LNIL:
- break;
- default:
- return -1;
- }
- if (unfp_list_deser(&list, buf, pos, rec) < 0)
- return -1;
- if (!(*term = unfy_term(UNFY_LIST, list, rec))) {
- unfy_recycle_list(rec, list);
- return -1;
- }
- return 0;
- }
- const char *
- unfp_term_deserable(const unsigned char *buf, size_t *pos, const size_t max)
- {
- if (!buf || *pos >= max)
- return "Not enough space for term";
- switch (*buf) {
- case UNFP_TNIL:
- case UNFP_IGN:
- ++*pos;
- return NULL;
- case UNFP_CONST:
- case UNFP_VAR:
- if (*pos + sizeof(Rid) + 1 > max) {
- *pos = max;
- return "Not enough space for id";
- }
- *pos += sizeof(Rid) + 1;
- return NULL;
- case UNFP_ORDER:
- if (*pos + sizeof(uint64_t) + 1 > max) {
- *pos = max;
- return "Not enough space for order";
- }
- *pos += sizeof(uint64_t) + 1;
- return NULL;
- case UNFP_LNIL:
- case UNFP_LOPEN:
- return unfp_list_deserable(buf, pos, max);
- default:
- break;
- }
- return "Not a valid term type";
- }
- /* list */
- void
- unfp_list_print(const Unfy_list *list)
- {
- printf("(");
- if (!list) {
- printf(")");
- return;
- }
- unfp_term_print(list->term);
- list = list->next;
- for (; list; list = list->next) {
- printf(" ");
- unfp_term_print(list->term);
- }
- printf(")");
- }
- int
- unfp_list_parse(Unfy_list **list, const char *str, size_t *pos,
- const char **error, Unfy_recycle *rec)
- {
- int first = 1;
- Unfy_list **tail = list;
- *list = NULL;
- if (*str != '(') {
- *error = "No bracket at start of list";
- return -1;
- }
- ++*pos;
- ++str;
- for (; isspace(*str); ++*pos, ++str);
- while (*str != ')') {
- size_t old = *pos;
- Unfy_term *term;
- if (!first) {
- if (unfp_space(str, pos, error) < 0)
- return -1;
- if (*(str += *pos - old) == ')')
- break;
- } else {
- first = 0;
- }
- old = *pos;
- if (!(term = unfp_term_parse(str, pos, error, rec))) {
- unfy_recycle_list(rec, *list);
- return -1;
- }
- str += *pos - old;
- if (!(tail = unfy_list_append(tail, term, rec))) {
- *error = "Failed to append to list";
- unfy_recycle_term(rec, term);
- unfy_recycle_list(rec, *list);
- return -1;
- }
- }
- ++*pos;
- return 0;
- }
- size_t
- unfp_list_len(const Unfy_list *list)
- {
- size_t len = 2;
- if (!list)
- return 1;
- for (; list; list = list->next)
- len += unfp_term_len(list->term);
- return len;
- }
- size_t
- unfp_list_write(const Unfy_list *list, unsigned char *buf)
- {
- int len = 1;
- if (!list) {
- *buf = UNFP_LNIL;
- return 1;
- }
- *buf = UNFP_LOPEN;
- for (; list; list = list->next)
- len += unfp_term_write(list->term, buf + len);
- buf[len] = UNFP_LCLOSE;
- return len + 1;
- }
- int
- unfp_list_ser(const Unfy_list *list, unsigned char **buf,
- size_t *size, size_t *pos)
- {
- size_t len = unfp_list_len(list);
- if (*size < len) {
- unsigned char *new_buf = realloc(*buf, len);
- if (!new_buf)
- return -1;
- *buf = new_buf;
- *size = len;
- }
- unfp_list_write(list, *buf);
- *pos += len;
- return 0;
- }
- int
- unfp_list_deser(Unfy_list **list, const unsigned char *buf,
- size_t *pos, Unfy_recycle *rec)
- {
- Unfy_list **end = list;
- *list = NULL;
- if (*buf == UNFP_LNIL) {
- ++*pos;
- return 0;
- }
- if (*buf != UNFP_LOPEN)
- return -1;
- ++*pos;
- ++buf;
- do {
- Unfy_term *term;
- size_t tmp = 0;
- if (unfp_term_deser(&term, buf, &tmp, rec) < 0) {
- unfy_recycle_list(rec, *list);
- return -1;
- }
- if (!(end = unfy_list_append(end, term, rec))) {
- unfy_recycle_term(rec, term);
- unfy_recycle_list(rec, *list);
- return -1;
- }
- *pos += tmp;
- buf += tmp;
- } while (*buf != UNFP_LCLOSE);
- ++*pos;
- return 0;
- }
- const char *
- unfp_list_deserable(const unsigned char *buf, size_t *pos, const size_t max)
- {
- const char *error;
- if (!buf || *pos >= max)
- return "Not enough space for list";
- switch (*buf) {
- case UNFP_LNIL:
- ++*pos;
- return NULL;
- case UNFP_LOPEN:
- break;
- default:
- return "Missing list byte";
- }
- ++*pos;
- ++buf;
- do {
- size_t tmp = *pos;
- if ((error = unfp_term_deserable(buf, pos, max)))
- return error;
- if (*pos + 1 > max) {
- *pos = max;
- return "Missing list close byte";
- }
- buf += *pos - tmp;
- } while (*buf != UNFP_LCLOSE);
- ++*pos;
- return NULL;
- }
- /* bind */
- void
- unfp_bind_print(const Unfy_bind *bind)
- {
- Rid_fn85 str;
- if (!bind) {
- printf("EMPTY");
- return;
- }
- rid_fn85(str, bind->var_id);
- printf("var %s -> ", str);
- unfp_term_print(bind->term);
- }
- void
- unfp_binds_print(const Unfy_bind *bind, int level)
- {
- if (!bind) {
- for (int i = 0; i < level; ++i)
- printf("\t");
- printf("EMPTY\n");
- return;
- }
- for (; bind; bind = bind->next) {
- for (int i = 0; i < level; ++i)
- printf("\t");
- unfp_bind_print(bind);
- printf("\n");
- }
- }
- int
- unfp_space(const char *str, size_t *pos, const char **error)
- {
- if (!isspace(*str)) {
- *error = "Missing a space";
- return -1;
- }
- ++str;
- ++*pos;
- for (; isspace(*str); ++str, ++*pos);
- return 0;
- }
- size_t
- unfp_bind_len(const Unfy_bind *bind)
- {
- size_t len = 2;
- if (!bind)
- return 1;
- for (; bind; bind = bind->next)
- len += unfp_term_len(bind->term) + sizeof(bind->var_id);
- return len;
- }
- size_t
- unfp_bind_write(const Unfy_bind *bind, unsigned char *buf)
- {
- int len = 1;
- if (!bind) {
- *buf = UNFP_BNIL;
- return 1;
- }
- *buf = UNFP_BOPEN;
- for (; bind; bind = bind->next) {
- len += unfp_term_write(bind->term, buf + len);
- rid_set(buf + len, bind->var_id);
- len += sizeof(bind->var_id);
- }
- buf[len] = UNFP_BCLOSE;
- return len + 1;
- }
- int
- unfp_bind_ser(const Unfy_bind *bind, unsigned char **buf,
- size_t *size, size_t *pos)
- {
- size_t len = unfp_bind_len(bind);
- if (*size < len) {
- unsigned char *new_buf = realloc(*buf, len);
- if (!new_buf)
- return -1;
- *buf = new_buf;
- *size = len;
- }
- unfp_bind_write(bind, *buf);
- *pos += len;
- return 0;
- }
- int
- unfp_bind_deser(Unfy_bind **bind, const unsigned char *buf,
- size_t *pos, Unfy_recycle *rec)
- {
- Unfy_bind **end = bind;
- *bind = NULL;
- if (*buf == UNFP_BNIL) {
- ++*pos;
- return 0;
- }
- if (*buf != UNFP_BOPEN)
- return -1;
- ++*pos;
- ++buf;
- do {
- Unfy_term *term;
- size_t tmp = 0;
- Rid var_id;
- if (unfp_term_deser(&term, buf, &tmp, rec) < 0) {
- unfy_recycle_bind(rec, *bind);
- return -1;
- }
- rid_set(var_id, buf + tmp);
- tmp += sizeof(var_id);
- if (unfy_bind(end, var_id, term, rec) < 0) {
- unfy_recycle_term(rec, term);
- unfy_recycle_bind(rec, *bind);
- return -1;
- }
- *pos += tmp;
- buf += tmp;
- *(end = &(*end)->next) = NULL;
- } while (*buf != UNFP_BCLOSE);
- ++*pos;
- return 0;
- }
- const char *
- unfp_bind_deserable(const unsigned char *buf, size_t *pos, const size_t max)
- {
- const char *error;
- if (!buf || *pos >= max)
- return "Not enough space for bind";
- switch (*buf) {
- case UNFP_BNIL:
- ++*pos;
- return NULL;
- case UNFP_BOPEN:
- break;
- default:
- return "Missing bind byte";
- }
- ++*pos;
- ++buf;
- do {
- size_t tmp = *pos;
- if ((error = unfp_term_deserable(buf, pos, max)))
- return error;
- if (*pos + sizeof(Rid) + 1 > max) {
- *pos = max;
- return "Content of bind exceeds maximum";
- }
- *pos += sizeof(Rid);
- buf += *pos - tmp;
- } while (*buf != UNFP_BCLOSE);
- ++*pos;
- return NULL;
- }
|