#include #include #include #include "spho/spho.h" #include "spho/ctx.h" #include "spho/scope.h" #include "spho/bind.h" static void spho_nom_term(struct spho_nom *); static int scope_nom_lookup_str_local(struct spho_scope *, const char *, size_t, struct spho_nom **); static int scope_nom_in_local(struct spho_scope *, struct spho_nom *); int spho_scope_init(struct spho_scope *sc, struct spho_ctx *ctx, struct spho_scope *p) { sc->ctx = ctx; sc->parent = p; SLIST_INIT(&sc->subs); SLIST_INIT(&sc->noms); sc->n_noms = 0; TAILQ_INIT(&sc->tps); sc->bind_loc = NULL; return (0); } void spho_scope_term(struct spho_scope *sc) { SPHO_UTIL_SLIST_DESTROY(&sc->subs, spho_scope, next, spho_scope_term); SPHO_UTIL_SLIST_DESTROY(&sc->noms, spho_nom, next, spho_nom_term); sc->parent = NULL; if (sc->bind_loc == NULL) spho_prebind_free(sc->bind_loc); sc->bind_loc = NULL; } struct spho_scope * spho_scope_global(struct spho_ctx *ctx) { SPHO_PRECOND(ctx != NULL); return (&ctx->glob); } struct spho_scope * spho_scope_create(struct spho_scope *sc) { struct spho_scope *sub; if ((sub = malloc(sizeof(struct spho_scope))) == NULL) { SPHO_ERR(sc->ctx, SPHO_ERR_SYS); return (NULL); } if (spho_scope_init(sub, sc->ctx, sc) == -1) { free(sub); return (NULL); } SLIST_INSERT_HEAD(&sc->subs, sub, next); return (sub); } static void spho_nom_term(__attribute__((unused)) struct spho_nom *nom) { return; } void spho_scope_destroy(struct spho_scope *sc) { struct spho_scope *p; p = sc->parent; SLIST_REMOVE(&p->subs, sc, spho_scope, next); spho_scope_term(sc); free(sc); } struct spho_nom * spho_scope_nom_add(struct spho_scope *sc, const char *nomstr, size_t sz) { size_t res; struct spho_nom *nom; nom = NULL; if (scope_nom_lookup_str_local(sc, nomstr, sz, &nom) == -1) return (NULL); if (nom != NULL) { SPHO_SC_ERR(sc, SPHO_ERR_NOM_INUSE); return (NULL); } if ((nom = malloc(sizeof(struct spho_nom))) == NULL) { SPHO_SC_ERR(sc, SPHO_ERR_SYS); return (NULL); } res = strlcpy(nom->s, nomstr, sizeof(nom->s)); if (res >= sizeof(nom->s)) { SPHO_SC_ERR(sc, SPHO_ERR_TOOBIG); goto err; } SLIST_INSERT_HEAD(&sc->noms, nom, next); sc->n_noms++; return (nom); err: free(nom); return (NULL); } int spho_scope_nom_lookup_str(struct spho_scope *sc, const char *nomstr, size_t sz, struct spho_nom **out) { struct spho_nom *nom; nom = NULL; if (sz > sizeof(nom->s)) { SPHO_ERR(sc->ctx, SPHO_ERR_TOOBIG); return (-1); } *out = NULL; while (*out == NULL && sc != NULL) { SLIST_FOREACH(nom, &sc->noms, next) { if (strncmp(nom->s, nomstr, sz) == 0) { *out = nom; break; } } sc = sc->parent; } return (0); } int spho_scope_nom_lookup_str_strict(struct spho_scope *sc, const char *nomstr, size_t sz, struct spho_nom **out) { if (spho_scope_nom_lookup_str(sc, nomstr, sz, out) == -1) return (-1); if (*out == NULL) { SPHO_SC_ERR(sc, SPHO_ERR_NOM_NOTINSCOPE); return (-1); } return (0); } int spho_scope_prebind_init(struct spho_scope *sc) { if ((sc->bind_loc = spho_prebind_create(sc)) == NULL) { return (-1); } return (0); } int spho_scope_prebind_tp(struct spho_scope *sc, struct spho_nom *nom, struct spho_tp *tp) { if (! scope_nom_in_local(sc, nom)) { SPHO_ERR(sc->ctx, SPHO_ERR_NOM_NOTINSCOPE); return (-1); } return (spho_prebind_tp(sc->bind_loc, nom, tp)); } int spho_scope_prebind_tp_op(struct spho_scope *sc, struct spho_nom *nom, struct spho_tp_op *tp_op) { if (! scope_nom_in_local(sc, nom)) { SPHO_ERR(sc->ctx, SPHO_ERR_NOM_NOTINSCOPE); return (-1); } return (spho_prebind_tp_op(sc->bind_loc, nom, tp_op)); } int spho_scope_prebind_undef(struct spho_scope *sc, struct spho_nom *nom) { if (! scope_nom_in_local(sc, nom)) { SPHO_ERR(sc->ctx, SPHO_ERR_NOM_NOTINSCOPE); return (-1); } return (spho_prebind_undef(sc->bind_loc, nom)); } static int scope_nom_lookup_str_local(struct spho_scope *sc, const char *nomstr, size_t sz, struct spho_nom **out) { struct spho_nom *nom; nom = NULL; if (sz > sizeof(nom->s)) { SPHO_ERR(sc->ctx, SPHO_ERR_TOOBIG); return (-1); } *out = NULL; SLIST_FOREACH(nom, &sc->noms, next) { if (strncmp(nom->s, nomstr, sz) == 0) { *out = nom; break; } } return (0); } static int scope_nom_in_local(struct spho_scope *sc, struct spho_nom *nom) { struct spho_nom *sc_nom; SLIST_FOREACH(sc_nom, &sc->noms, next) { if (sc_nom == nom) return (1); } return (0); }