int val_stringp(const cst_val *v) { if (cst_val_consp(v)) return FALSE; else if (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING) return TRUE; else return FALSE; }
const cst_val *val_cdr(const cst_val *v) { if (v && cst_val_consp(v)) return CST_VAL_CDR(v); else { cst_errmsg("VAL: tried to access cdr in %d typed val\n", (v ? CST_VAL_TYPE(v) : -1)); cst_error(); } return 0; }
void delete_val_list(cst_val *v) { if (v) { if (cst_val_consp(v)) { delete_val_list(CST_VAL_CDR(v)); cst_free(v); } else delete_val(v); } }
cst_val *val_inc_refcount(const cst_val *b) { cst_val *wb; /* Well I was lying, they're not really const, but this is the place */ /* where breaking const is reasonable */ wb = (cst_val *)(void *)b; if (CST_VAL_REFCOUNT(wb) == -1) /* or is a cons cell in the text segment, how do I do that ? */ return wb; else if (!cst_val_consp(wb)) /* we don't ref count cons cells */ CST_VAL_REFCOUNT(wb) += 1; return wb; }
const cst_val *set_car(cst_val *v1, const cst_val *v2) { /* destructive set car, be careful you have a pointer to current cdr */ if (!cst_val_consp(v1)) { cst_errmsg("VAL: tried to set car of non-consp cell\n"); cst_error(); return NULL; } else { val_dec_refcount(CST_VAL_CAR(v1)); val_inc_refcount(v1); CST_VAL_CAR(v1) = (cst_val *)v2; } return v1; }
void delete_val(cst_val *v) { if (v) { if (cst_val_consp(v)) { delete_val(CST_VAL_CAR(v)); delete_val(CST_VAL_CDR(v)); cst_free(v); } else if (val_dec_refcount(v) == 0) { if (CST_VAL_TYPE(v) == CST_VAL_TYPE_STRING) cst_free(CST_VAL_VOID(v)); else if (CST_VAL_TYPE(v) >= CST_VAL_TYPE_FIRST_FREE) (cst_val_defs[CST_VAL_TYPE(v)/2].delete_function)(CST_VAL_VOID(v)); cst_free(v); } } }
int val_equal(const cst_val *v1, const cst_val *v2) { if (v1 == v2) return TRUE; /* its eq so its equal */ else if (v1 == 0) return FALSE; else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE(v2)) { if (cst_val_consp(v1)) return ((val_equal(val_car(v1),val_car(v2))) && (val_equal(val_cdr(v1),val_cdr(v2)))); else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE_INT) return (val_int(v1) == val_int(v2)); else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE_FLOAT) return (val_float(v1) == val_float(v2)); else if (CST_VAL_TYPE(v1) == CST_VAL_TYPE_STRING) return (cst_streq(CST_VAL_STRING(v1),CST_VAL_STRING(v2))); else return CST_VAL_VOID(v1) == CST_VAL_VOID(v2); } else return FALSE; }
cst_utterance *default_textanalysis(cst_utterance *u) { cst_item *t,*word; cst_relation *word_rel; cst_val *words; const cst_val *w; const cst_val *ttwv; word_rel = utt_relation_create(u,"Word"); ttwv = feat_val(u->features, "tokentowords_func"); for (t=relation_head(utt_relation(u,"Token")); t; t=item_next(t)) { if (ttwv) words = (cst_val *)(*val_itemfunc(ttwv))(t); else words = default_tokentowords(t); for (w=words; w; w=val_cdr(w)) { word = item_add_daughter(t,NULL); if (cst_val_consp(val_car(w))) { /* Has extra features */ item_set_string(word,"name",val_string(val_car(val_car(w)))); feat_copy_into(val_features(val_cdr(val_car(w))), item_feats(word)); } else item_set_string(word,"name",val_string(val_car(w))); relation_append(word_rel,word); } delete_val(words); } return u; }
int val_dec_refcount(const cst_val *b) { cst_val *wb; wb = (cst_val *)(void *)b; if (CST_VAL_REFCOUNT(wb) == -1) /* or is a cons cell in the text segment, how do I do that ? */ return -1; else if (cst_val_consp(wb)) /* we don't ref count cons cells */ return 0; else if (CST_VAL_REFCOUNT(wb) == 0) { /* Otherwise, trying to free a val outside an item/relation/etc has rather the opposite effect from what you might have intended... */ return 0; } else { CST_VAL_REFCOUNT(wb) -= 1; return CST_VAL_REFCOUNT(wb); } }