X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fcqltransform.c;h=41726776cde869d08db6b27f3f12e12b147c1d37;hp=ef93ca86568ce1796cb5413b324dc526b9c7f845;hb=7fc0a649c80cade7f443c6deb552e1907be9af22;hpb=5242cb5a8634bfa38b9333ff7f903e718ac6e292 diff --git a/src/cqltransform.c b/src/cqltransform.c index ef93ca8..4172677 100644 --- a/src/cqltransform.c +++ b/src/cqltransform.c @@ -1,5 +1,5 @@ /* This file is part of the YAZ toolkit. - * Copyright (C) 1995-2012 Index Data + * Copyright (C) Index Data * See the file LICENSE for details. */ /** @@ -45,7 +45,6 @@ struct cql_transform_t_ { yaz_tok_cfg_t tok_cfg; int error; char *addinfo; - WRBUF w; NMEM nmem; }; @@ -54,7 +53,6 @@ cql_transform_t cql_transform_create(void) { cql_transform_t ct = (cql_transform_t) xmalloc(sizeof(*ct)); ct->tok_cfg = yaz_tok_cfg_create(); - ct->w = wrbuf_alloc(); ct->error = 0; ct->addinfo = 0; ct->entry = 0; @@ -70,6 +68,8 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, Z_AttributeElement *ae[20]; int ret = 0; /* 0=OK, != 0 FAIL */ int t; + WRBUF w = wrbuf_alloc(); + t = yaz_tok_move(tp); while (t == YAZ_TOK_STRING && ae_num < 20) @@ -83,7 +83,7 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, elem = (Z_AttributeElement *) nmem_malloc(ct->nmem, sizeof(*elem)); elem->attributeSet = 0; ae[ae_num] = elem; - wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); + wrbuf_puts(w, yaz_tok_parse_string(tp)); wrbuf_puts(type_str, yaz_tok_parse_string(tp)); t = yaz_tok_move(tp); if (t == YAZ_TOK_EOF) @@ -95,8 +95,8 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, } if (t == YAZ_TOK_STRING) { - wrbuf_puts(ct->w, " "); - wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); + wrbuf_puts(w, " "); + wrbuf_puts(w, yaz_tok_parse_string(tp)); set_str = type_str; elem->attributeSet = @@ -159,10 +159,10 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, ca->num_semanticAction = 0; ca->semanticAction = 0; } - wrbuf_puts(ct->w, "="); - wrbuf_puts(ct->w, yaz_tok_parse_string(tp)); + wrbuf_puts(w, "="); + wrbuf_puts(w, yaz_tok_parse_string(tp)); t = yaz_tok_move(tp); - wrbuf_puts(ct->w, " "); + wrbuf_puts(w, " "); ae_num++; } if (ret == 0) /* OK? */ @@ -172,7 +172,7 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, pp = &(*pp)->next; *pp = (struct cql_prop_entry *) xmalloc(sizeof(**pp)); (*pp)->pattern = xstrdup(pattern); - (*pp)->value = xstrdup(wrbuf_cstr(ct->w)); + (*pp)->value = xstrdup(wrbuf_cstr(w)); (*pp)->attr_list.num_attributes = ae_num; if (ae_num == 0) @@ -197,6 +197,7 @@ static int cql_transform_parse_tok_line(cql_transform_t ct, odr_destroy(pr); } } + wrbuf_destroy(w); return ret; } @@ -222,7 +223,6 @@ cql_transform_t cql_transform_open_FILE(FILE *f) { yaz_tok_parse_t tp = yaz_tok_parse_buf(ct->tok_cfg, line); int t; - wrbuf_rewind(ct->w); t = yaz_tok_move(tp); if (t == YAZ_TOK_STRING) { @@ -269,7 +269,6 @@ void cql_transform_close(cql_transform_t ct) } xfree(ct->addinfo); yaz_tok_cfg_destroy(ct->tok_cfg); - wrbuf_destroy(ct->w); nmem_destroy(ct->nmem); xfree(ct); } @@ -575,25 +574,6 @@ static int cql_pr_prox(cql_transform_t ct, struct cql_node *mods, return 1; } -/* Returns location of first wildcard character in the `length' - * characters starting at `term', or a null pointer of there are - * none -- like memchr(). - */ -static const char *wcchar(int start, const char *term, int length) -{ - while (length > 0) - { - if (start || term[-1] != '\\') - if (strchr("*?", *term)) - return term; - term++; - length--; - start = 0; - } - return 0; -} - - /* ### checks for CQL relation-name rather than Type-1 attribute */ static int has_modifier(struct cql_node *cn, const char *name) { struct cql_node *mod; @@ -605,7 +585,6 @@ static int has_modifier(struct cql_node *cn, const char *name) { return 0; } - static void emit_term(cql_transform_t ct, struct cql_node *cn, const char *term, int length, @@ -619,6 +598,8 @@ static void emit_term(cql_transform_t ct, if (has_modifier(cn, "regexp")) process_term = 0; + else if (has_modifier(cn, "unmasked")) + process_term = 0; else if (cql_lookup_property(ct, "truncation", 0, "cql")) { process_term = 0; @@ -627,23 +608,53 @@ static void emit_term(cql_transform_t ct, } assert(cn->which == CQL_NODE_ST); - if (process_term && length > 0) - { - if (length > 1 && term[0] == '^' && term[length-1] == '^') + if (process_term) + { /* convert term via truncation.things */ + unsigned anchor = 0; + unsigned trunc = 0; + for (i = 0; i < length; i++) + { + if (term[i] == '\\' && i < length - 1) + i++; + else + { + switch (term[i]) + { + case '^': + if (i == 0) + anchor |= 1; + else if (i == length - 1) + anchor |= 2; + break; + case '*': + if (i == 0) + trunc |= 1; + else if (i == length - 1) + trunc |= 2; + else + z3958_mode = 1; + break; + case '?': + z3958_mode = 1; + break; + } + } + } + if (anchor == 3) { cql_pr_attr(ct, "position", "firstAndLast", 0, pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); term++; length -= 2; } - else if (term[0] == '^') + else if (anchor == 1) { cql_pr_attr(ct, "position", "first", 0, pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); term++; length--; } - else if (term[length-1] == '^') + else if (anchor == 2) { cql_pr_attr(ct, "position", "last", 0, pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); @@ -654,53 +665,34 @@ static void emit_term(cql_transform_t ct, cql_pr_attr(ct, "position", "any", 0, pr, client_data, YAZ_SRW_ANCHORING_CHAR_IN_UNSUPP_POSITION); } - } - - if (process_term && length > 0) - { - const char *first_wc = wcchar(1, term, length); - const char *second_wc = first_wc ? - wcchar(0, first_wc+1, length-(first_wc-term)-1) : 0; - - /* Check for well-known globbing patterns that represent - * simple truncation attributes as expected by, for example, - * Bath-compliant server. If we find such a pattern but - * there's no mapping for it, that's fine: we just use a - * general pattern-matching attribute. - */ - if (first_wc == term && second_wc == term + length-1 - && *first_wc == '*' && *second_wc == '*' - && cql_pr_attr(ct, "truncation", "both", 0, pr, client_data, 0)) - { - term++; - length -= 2; - } - else if (first_wc == term && second_wc == 0 && *first_wc == '*' - && cql_pr_attr(ct, "truncation", "left", 0, - pr, client_data, 0)) - { - term++; - length--; - } - else if (first_wc == term + length-1 && second_wc == 0 - && *first_wc == '*' - && cql_pr_attr(ct, "truncation", "right", 0, - pr, client_data, 0)) + if (z3958_mode == 0) { - length--; + if (trunc == 3 && cql_pr_attr(ct, "truncation", + "both", 0, pr, client_data, 0)) + { + term++; + length -= 2; + } + else if (trunc == 1 && cql_pr_attr(ct, "truncation", + "left", 0, pr, client_data, 0)) + { + term++; + length--; + } + else if (trunc == 2 && cql_pr_attr(ct, "truncation", "right", 0, + pr, client_data, 0)) + { + length--; + } + else if (trunc) + z3958_mode = 1; + else + cql_pr_attr(ct, "truncation", "none", 0, + pr, client_data, 0); } - else if (first_wc) - { - z3958_mode = 1; + if (z3958_mode) cql_pr_attr(ct, "truncation", "z3958", 0, pr, client_data, YAZ_SRW_MASKING_CHAR_UNSUPP); - } - else - { - /* No masking characters. Use "truncation.none" if given. */ - cql_pr_attr(ct, "truncation", "none", 0, - pr, client_data, 0); - } } if (ns) { cql_pr_attr_uri(ct, "index", ns, @@ -716,42 +708,48 @@ static void emit_term(cql_transform_t ct, pr, client_data, YAZ_SRW_UNSUPP_RELATION_MODIFIER); } } - - /* produce only \-sequences if: - 1) the output is a Z39.58-trunc reserved character - 2) the output is a PQF reserved character (\\, \") - */ (*pr)("\"", client_data); - for (i = 0; i < length; i++) - { - char x[3]; /* temp buffer */ - if (i > 0 && term[i-1] == '\\') + if (process_term) + for (i = 0; i < length; i++) { - if (term[i] == '\"' || term[i] == '\\') - pr("\\", client_data); - if (z3958_mode && strchr("#?", term[i])) - pr("\\\\", client_data); /* double \\ to survive PQF parse */ - x[0] = term[i]; - x[1] = '\0'; - pr(x, client_data); + char x[2]; /* temp buffer */ + if (term[i] == '\\' && i < length - 1) + { + i++; + if (strchr("\"\\", term[i])) + pr("\\", client_data); + if (z3958_mode && strchr("#?", term[i])) + pr("\\\\", client_data); /* double \\ to survive PQF parse */ + x[0] = term[i]; + x[1] = '\0'; + pr(x, client_data); + } + else if (z3958_mode && term[i] == '*') + { + pr("?", client_data); + if (i < length - 1 && yaz_isdigit(term[i+1])) + pr("\\\\", client_data); /* dbl \\ to survive PQF parse */ + } + else if (z3958_mode && term[i] == '?') + { + pr("#", client_data); + } + else + { + if (term[i] == '\"') + pr("\\", client_data); + if (z3958_mode && strchr("#?", term[i])) + pr("\\\\", client_data); /* dbl \\ to survive PQF parse */ + x[0] = term[i]; + x[1] = '\0'; + pr(x, client_data); + } } - else if (z3958_mode && term[i] == '*') - { - pr("?", client_data); - /* avoid ?n sequences output (n=[0-9]) because that has - different semantics than just a single ? in Z39.58 - */ - if (i < length - 1 && yaz_isdigit(term[i+1])) - pr("\\\\", client_data); /* double \\ to survive PQF parse */ - } - else if (z3958_mode && term[i] == '?') - pr("#", client_data); - else if (term[i] != '\\') + else + { + for (i = 0; i < length; i++) { - if (term[i] == '\"') - pr("\\", client_data); - if (z3958_mode && strchr("#?", term[i])) - pr("\\\\", client_data); /* double \\ to survive PQF parse */ + char x[2]; x[0] = term[i]; x[1] = '\0'; pr(x, client_data);