static struct value *lns_value_of_type(struct info *info, struct regexp *rx) { struct value *result = make_value(V_REGEXP, ref(info)); if (rx) result->regexp = ref(rx); else result->regexp = regexp_make_empty(ref(info)); return result; }
/* * Lens primitives */ struct value *lns_make_prim(enum lens_tag tag, struct info *info, struct regexp *regexp, struct string *string) { struct lens *lens = NULL; struct value *exn = NULL; struct fa *fa_slash = NULL; struct fa *fa_key = NULL; struct fa *fa_isect = NULL; /* Typecheck */ if (tag == L_KEY) { exn = str_to_fa(info, "(.|\n)*/(.|\n)*", &fa_slash); if (exn != NULL) goto error; exn = regexp_to_fa(regexp, &fa_key); if (exn != NULL) goto error; fa_isect = fa_intersect(fa_slash, fa_key); if (! fa_is_basic(fa_isect, FA_EMPTY)) { exn = make_exn_value(info, "The key regexp /%s/ matches a '/'", regexp->pattern->str); goto error; } fa_free(fa_isect); fa_free(fa_key); fa_free(fa_slash); fa_isect = fa_key = fa_slash = NULL; } else if (tag == L_LABEL) { if (strchr(string->str, SEP) != NULL) { exn = make_exn_value(info, "The label string \"%s\" contains a '/'", string->str); goto error; } } else if (tag == L_DEL) { int cnt; const char *dflt = string->str; cnt = regexp_match(regexp, dflt, strlen(dflt), 0, NULL); if (cnt != strlen(dflt)) { char *s = escape(dflt, -1); char *r = escape(regexp->pattern->str, -1); exn = make_exn_value(info, "del: the default value '%s' does not match /%s/", s, r); FREE(s); FREE(r); goto error; } } /* Build the actual lens */ lens = make_lens(tag, info); lens->regexp = regexp; lens->string = string; lens->key = (tag == L_KEY || tag == L_LABEL || tag == L_SEQ); lens->value = (tag == L_STORE); lens->consumes_value = (tag == L_STORE); lens->atype = regexp_make_empty(info); if (tag == L_DEL || tag == L_STORE || tag == L_KEY) { lens->ctype = ref(regexp); } else if (tag == L_LABEL || tag == L_SEQ || tag == L_COUNTER) { lens->ctype = regexp_make_empty(info); } else { assert(0); } return make_lens_value(lens); error: fa_free(fa_isect); fa_free(fa_key); fa_free(fa_slash); return exn; }