123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- /* This file is part of rls.
- *
- * Rls 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.
- *
- * Rls 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 rls. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <ctype.h>
- #include <endian.h>
- #include <inttypes.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/unfy.h>
- #include <unfy/unfp.h>
- #include "rls.h"
- #include "rlsp.h"
- /* length of constant size data for rule */
- static const size_t core_len = sizeof(Rid) + 2 * sizeof(uint16_t) +
- sizeof(uint8_t);
- static Rls_rule *
- get_rule(Rls_recycle *rec)
- {
- Rls_rule *rule = rec->rules;
- if (!rule)
- return malloc(sizeof(*rule));
- rec->rules = rule->next;
- return rule;
- }
- static Rls_srch *
- get_srch(Rls_recycle *rec)
- {
- Rls_srch *srch = rec->srchs;
- if (!srch)
- return malloc(sizeof(*srch));
- rec->srchs = (void *) srch->body;
- return srch;
- }
- /* rule */
- void
- rlsp_rule_print(const Rls_rule *rule, Rlsp_dat_print dat_print)
- {
- if (!rule) {
- printf("Empty\n");
- return;
- }
- for (; rule; rule = rule->next) {
- Rid_fn85 str;
- rid_fn85(str, rule->id);
- printf("%s", str);
- if (dat_print)
- dat_print(rule->dat);
- printf(" ");
- unfp_term_print(rule->head);
- printf(" ");
- if (rule->actable)
- printf("ACT");
- else
- unfp_list_print(rule->u.body);
- printf("\n");
- }
- }
- size_t
- rlsp_rule_len(const Rls_rule *rules, Rlsp_srlz *srlz, void *extra)
- {
- size_t len = 2;
- if (!rules)
- return 1;
- for (; rules; rules = rules->next) {
- len += 1 + core_len + unfp_term_len(rules->head);
- if (srlz)
- len += srlz->len(rules, extra);
- if (!rules->actable)
- len += unfp_list_len(rules->u.body);
- }
- return len;
- }
- size_t
- rlsp_rule_write(const Rls_rule *rules, unsigned char *buf,
- Rlsp_srlz *srlz, void *extra)
- {
- size_t len = 1;
- if (!rules) {
- *buf = RLSP_RNIL;
- return 1;
- }
- *buf = RLSP_ROPEN;
- for (; rules; rules = rules->next) {
- *(buf + len) = RLSP_RULE;
- ++len;
- rid_set(buf + len, rules->id);
- len += sizeof(rules->id);
- *(uint16_t *)(buf + len) = htole16(rules->size);
- len += sizeof(rules->size);
- *(uint16_t *)(buf + len) = htole16(rules->max_binds);
- len += sizeof(rules->max_binds);
- *(buf + len) = rules->actable;
- len += sizeof(rules->actable);
- len += unfp_term_write(rules->head, buf + len);
- if (srlz)
- len += srlz->write(rules, buf + len, extra);
- if (!rules->actable)
- len += unfp_list_write(rules->u.body, buf + len);
- }
- buf[len] = RLSP_RCLOSE;
- return len + 1;
- }
- int
- rlsp_rule_ser(const Rls_rule *rules, unsigned char **buf, size_t *size,
- size_t *pos, Rlsp_srlz *srlz, void *extra)
- {
- size_t len = rlsp_rule_len(rules, srlz, extra);
- if (*size < len) {
- unsigned char *new_buf = realloc(*buf, len);
- if (!new_buf)
- return -1;
- *buf = new_buf;
- *size = len;
- }
- rlsp_rule_write(rules, *buf, srlz, extra);
- *pos += len;
- return 0;
- }
- int
- rlsp_rule_deser(Rls_rule **rules, const unsigned char *buf, size_t *pos,
- Rlsp_srlz *srlz, void *extra, Rls_recycle *rec)
- {
- Rls_rule **end = rules;
- Rls_dat_free dat_free = srlz ? srlz->dat_free : NULL;
- *rules = NULL;
- if (*buf == RLSP_RNIL) {
- ++*pos;
- return 0;
- }
- if (*buf != RLSP_ROPEN)
- return -1;
- ++*pos;
- ++buf;
- do {
- size_t tmp = 1;
- if (*buf != RLSP_RULE || !(*end = get_rule(rec))) {
- rls_recycle_rule(rec, *rules, dat_free, extra);
- *rules = NULL;
- return -1;
- }
- (*end)->next = NULL;
- rid_set((*end)->id, buf + tmp);
- tmp += sizeof((*end)->id);
- (*end)->size = le16toh(*(uint16_t *)(buf + tmp));
- tmp += sizeof((*end)->size);
- (*end)->max_binds = le16toh(*(uint16_t *)(buf + tmp));
- tmp += sizeof((*end)->max_binds);
- (*end)->actable = *(buf + tmp);
- tmp += sizeof((*end)->actable);
- if (unfp_term_deser(&(*end)->head, buf + tmp,
- &tmp, &rec->unfy) < 0) {
- *pos += tmp;
- goto err;
- }
- *pos += tmp;
- buf += tmp;
- tmp = 0;
- if (srlz && srlz->deser(*end, buf, &tmp, extra) < 0)
- goto err;
- if (!(*end)->actable &&
- unfp_list_deser(&(*end)->u.body, buf + tmp,
- &tmp, &rec->unfy) < 0)
- goto err;
- *pos += tmp;
- buf += tmp;
- end = &(*end)->next;
- } while (*buf != RLSP_RCLOSE);
- ++*pos;
- return 0;
- err:
- /* This bit is a little hackish, basically makes this
- unfinished rule recyclable */
- (*end)->actable = 1;
- rls_recycle_rule(rec, *rules, dat_free, extra);
- *rules = NULL;
- return -1;
- }
- const char *
- rlsp_rule_deserable(const unsigned char *buf, size_t *pos,
- const size_t max, Rlsp_srlz *srlz, void *extra)
- {
- const char *error;
- if (!buf || *pos >= max)
- return "Not enough space for rule";
- switch (*buf) {
- case RLSP_RNIL:
- ++*pos;
- return NULL;
- case RLSP_ROPEN:
- break;
- default:
- return "Missing rule byte";
- }
- ++*pos;
- ++buf;
- do {
- size_t tmp = 0;
- uint8_t actable;
- if (*buf != RLSP_RULE)
- return "Missing rule byte";
- ++*pos;
- ++buf;
- if (*pos + core_len > max) {
- *pos = max;
- return "Content of rule exceeds maximum";
- }
- tmp = (*pos += core_len);
- buf += core_len;
- actable = buf[-1];
- if ((error = unfp_term_deserable(buf, pos, max)))
- return error;
- buf += *pos - tmp;
- tmp = *pos;
- if (srlz && (error = srlz->deserable(buf, pos, max, extra)))
- return error;
- buf += *pos - tmp;
- tmp = *pos;
- if (!actable && (error = unfp_list_deserable(buf, pos, max)))
- return error;
- buf += *pos - tmp;
- if (*pos + 1 > max)
- return "Missing rule close byte";
- } while (*buf != RLSP_RCLOSE);
- ++*pos;
- return NULL;
- }
- /* srch */
- static void
- indent_level(int level)
- {
- for (int i = 0; i < level; ++i)
- printf("\t");
- }
- static void
- binds_flow_print(const Rls_srch *srch, int level)
- {
- Unfy_bind *bind = srch->nbind;
- indent_level(level);
- printf("Left\n");
- for (; bind; bind = bind->next) {
- Unfy_term *lterm = unfy_bind_get(srch->lbind, bind->term->u.id);
- Unfy_term *fterm = unfy_bind_get(srch->fbind, bind->var_id);
- indent_level(level + 1);
- unfp_bind_print(bind);
- if (lterm) {
- printf(" -> ");
- unfp_term_print(lterm);
- }
- if (fterm) {
- printf(" -> ");
- unfp_term_print(fterm);
- }
- printf("\n");
- }
- indent_level(level);
- printf("RIGHT\n");
- unfp_binds_print(srch->rbind, level + 1);
- }
- void
- rlsp_srch_print(const Rls_srch *srch, int level)
- {
- for (int i = 0; i < level; ++i)
- printf("\t");
- if (!srch) {
- printf("Empty\n");
- return;
- }
- printf("%" PRIu16 ".", srch->num);
- unfp_term_print(srch->term);
- printf("\n");
- binds_flow_print(srch, level + 1);
- if (!srch->rule->actable && srch->body)
- for (int i = 0; i < srch->rule->size; ++i)
- rlsp_srch_print(srch->body[i], level + 1);
- }
- size_t
- rlsp_srch_len(const Rls_srch *srch)
- {
- size_t len = 1 + sizeof(srch->rule->id) + sizeof(srch->num) +
- sizeof(srch->rule->size);
- if (!srch)
- return 1;
- len += unfp_term_len(srch->term) + unfp_bind_len(srch->lbind) +
- unfp_bind_len(srch->rbind) + unfp_bind_len(srch->nbind) +
- unfp_bind_len(srch->fbind);
- for (int i = 0; i < srch->rule->size; ++i)
- len += rlsp_srch_len(srch->body[i]);
- return len;
- }
- size_t
- rlsp_srch_write(const Rls_srch *srch, unsigned char *buf)
- {
- size_t len = 1;
- if (!srch) {
- *buf = RLSP_SNIL;
- return 1;
- }
- *buf = RLSP_SOPEN;
- rid_set(buf + len, srch->rule->id);
- len += sizeof(Rid);
- *(uint16_t *)(buf + len) = htole16(srch->num);
- len += sizeof(srch->num);
- *(uint16_t *)(buf + len) = htole16(srch->rule->size);
- len += sizeof(srch->rule->size);
- len += unfp_term_write(srch->term, buf + len);
- len += unfp_bind_write(srch->lbind, buf + len);
- len += unfp_bind_write(srch->rbind, buf + len);
- len += unfp_bind_write(srch->nbind, buf + len);
- len += unfp_bind_write(srch->fbind, buf + len);
- for (int i = 0; i < srch->rule->size; ++i)
- len += rlsp_srch_write(srch->body[i], buf + len);
- return len;
- }
- int
- rlsp_srch_ser(const Rls_srch *srch, unsigned char **buf,
- size_t *size, size_t *pos)
- {
- size_t len = rlsp_srch_len(srch);
- if (*size < len) {
- unsigned char *new_buf = realloc(*buf, len);
- if (!new_buf)
- return -1;
- *buf = new_buf;
- *size = len;
- }
- rlsp_srch_write(srch, *buf);
- *pos += len;
- return 0;
- }
- const char *
- rlsp_srch_deser(Rls_srch **srch, const unsigned char *buf, size_t *pos,
- Rls_rule *rules, Rls_bend bend, void *extra, Rls_recycle *rec)
- {
- size_t len;
- Rid rule_id;
- uint16_t num;
- uint16_t size;
- Rls_rule *rule = rules;
- Unfy_term *term;
- const char *error;
- if (*buf == RLSP_SNIL) {
- *srch = NULL;
- ++*pos;
- return NULL;
- }
- if (*buf != RLSP_SOPEN) {
- *srch = NULL;
- return "Missing srch byte";
- }
- len = 1;
- rid_set(rule_id, buf + len);
- len += sizeof(rule_id);
- num = le16toh(*(uint16_t *)(buf + len));
- len += sizeof(num);
- size = le16toh(*(uint16_t *)(buf + len));
- len += sizeof(size);
- if (unfp_term_deser(&term, buf + len, &len, &rec->unfy) < 0)
- return "Failed to deser term";
- if (bend) {
- Unfy_stat stat = UNFY_ERR;
- Rls_rule **tmp = bend(term, &stat, extra);
- if (!tmp) {
- /* we can't find the rule, so we can't deser */
- unfy_recycle_term(&rec->unfy, term);
- return "Failed rule bend";
- }
- rule = *tmp;
- }
- for (; rule && rid_cmp(rule->id, rule_id); rule = rule->next);
- if (!rule) {
- unfy_recycle_term(&rec->unfy, term);
- return "Rule not found";
- }
- if (!(*srch = get_srch(rec))) {
- unfy_recycle_term(&rec->unfy, term);
- return "Failed to allocate srch";
- }
- (*srch)->up = NULL;
- (*srch)->rule = rule;
- (*srch)->term = term;
- (*srch)->num = num;
- if (!size)
- (*srch)->body = NULL;
- else if (!((*srch)->body = calloc(size, sizeof(Rls_srch *)))) {
- error = "Failed to allocate body";
- goto body_err;
- }
- if (unfp_bind_deser(&(*srch)->lbind, buf + len, &len, &rec->unfy) < 0) {
- error = "Failed to deser lbind";
- goto lbind_err;
- }
- if (unfp_bind_deser(&(*srch)->rbind, buf + len, &len, &rec->unfy) < 0) {
- error = "Failed to deser rbind";
- goto rbind_err;
- }
- if (unfp_bind_deser(&(*srch)->nbind, buf + len, &len, &rec->unfy) < 0) {
- error = "Failed to deser nbind";
- goto nbind_err;
- }
- if (unfp_bind_deser(&(*srch)->fbind, buf + len, &len, &rec->unfy) < 0) {
- error = "Failed to deser fbind";
- goto full_err;
- }
- for (int i = 0; i < size; ++i) {
- if ((error = rlsp_srch_deser(&(*srch)->body[i], buf + len,
- &len, rules, bend, extra, rec)))
- goto full_err;
- (*srch)->body[i]->up = *srch;
- }
- *pos += len;
- return NULL;
- body_err:
- (*srch)->lbind = NULL;
- lbind_err:
- (*srch)->rbind = NULL;
- rbind_err:
- (*srch)->nbind = NULL;
- nbind_err:
- (*srch)->fbind = NULL;
- full_err:
- rls_recycle_srch(rec, *srch);
- *srch = NULL;
- return error;
- }
- const char *
- rlsp_srch_deserable(const unsigned char *buf, size_t *pos, const size_t max)
- {
- const char *error;
- uint16_t size;
- size_t tmp;
- if (!buf || *pos >= max)
- return "Not enough space for srch";
- switch (*buf) {
- case RLSP_SNIL:
- ++*pos;
- return NULL;
- case RLSP_SOPEN:
- break;
- default:
- return "Missing srch byte";
- }
- ++*pos;
- ++buf;
- if (*pos + sizeof(Rid) + 2 * sizeof(uint16_t) > max) {
- *pos = max;
- return NULL;
- }
- *pos += sizeof(Rid) + 2 * sizeof(uint16_t);
- buf += sizeof(Rid) + 2 * sizeof(uint16_t);
- size = ((uint16_t *) buf)[-1];
- tmp = *pos;
- if ((error = unfp_term_deserable(buf, pos, max)))
- return error;
- for (int i = 0; i < 4; ++i) {
- buf += *pos - tmp;
- tmp = *pos;
- if ((error = unfp_bind_deserable(buf, pos, max)))
- return error;
- }
- for (uint16_t i = 0; i < size; ++i) {
- buf += *pos - tmp;
- tmp = *pos;
- if ((error = rlsp_srch_deserable(buf, pos, max)))
- return error;
- }
- return NULL;
- }
|