+int cql_pr_attr(cql_transform_t ct, const char *category,
+ const char *val, const char *default_val,
+ void (*pr)(const char *buf, void *client_data),
+ void *client_data,
+ int errcode)
+{
+ return cql_pr_attr_uri(ct, category, 0 /* uri */,
+ val, default_val, pr, client_data, errcode);
+}
+
+
+static void cql_pr_int(int val,
+ void (*pr)(const char *buf, void *client_data),
+ void *client_data)
+{
+ char buf[21]; /* enough characters to 2^64 */
+ sprintf(buf, "%d", val);
+ (*pr)(buf, client_data);
+ (*pr)(" ", client_data);
+}
+
+
+static int cql_pr_prox(cql_transform_t ct, struct cql_node *mods,
+ void (*pr)(const char *buf, void *client_data),
+ void *client_data)
+{
+ int exclusion = 0;
+ int distance; /* to be filled in later depending on unit */
+ int distance_defined = 0;
+ int ordered = 0;
+ int proxrel = 2; /* less than or equal */
+ int unit = 2; /* word */
+
+ while (mods)
+ {
+ const char *name = mods->u.st.index;
+ const char *term = mods->u.st.term;
+ const char *relation = mods->u.st.relation;
+
+ if (!strcmp(name, "distance")) {
+ distance = strtol(term, (char**) 0, 0);
+ distance_defined = 1;
+ if (!strcmp(relation, "="))
+ proxrel = 3;
+ else if (!strcmp(relation, ">"))
+ proxrel = 5;
+ else if (!strcmp(relation, "<"))
+ proxrel = 1;
+ else if (!strcmp(relation, ">="))
+ proxrel = 4;
+ else if (!strcmp(relation, "<="))
+ proxrel = 2;
+ else if (!strcmp(relation, "<>"))
+ proxrel = 6;
+ else
+ {
+ ct->error = YAZ_SRW_UNSUPP_PROX_RELATION;
+ ct->addinfo = xstrdup(relation);
+ return 0;
+ }
+ }
+ else if (!strcmp(name, "ordered"))
+ ordered = 1;
+ else if (!strcmp(name, "unordered"))
+ ordered = 0;
+ else if (!strcmp(name, "unit"))
+ {
+ if (!strcmp(term, "word"))
+ unit = 2;
+ else if (!strcmp(term, "sentence"))
+ unit = 3;
+ else if (!strcmp(term, "paragraph"))
+ unit = 4;
+ else if (!strcmp(term, "element"))
+ unit = 8;
+ else
+ {
+ ct->error = YAZ_SRW_UNSUPP_PROX_UNIT;
+ ct->addinfo = xstrdup(term);
+ return 0;
+ }
+ }
+ else
+ {
+ ct->error = YAZ_SRW_UNSUPP_BOOLEAN_MODIFIER;
+ ct->addinfo = xstrdup(name);
+ return 0;
+ }
+ mods = mods->u.st.modifiers;
+ }
+
+ if (!distance_defined)
+ distance = (unit == 2) ? 1 : 0;
+
+ cql_pr_int(exclusion, pr, client_data);
+ cql_pr_int(distance, pr, client_data);
+ cql_pr_int(ordered, pr, client_data);
+ cql_pr_int(proxrel, pr, client_data);
+ (*pr)("k ", client_data);
+ cql_pr_int(unit, pr, client_data);
+
+ 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;
+ for (mod = cn->u.st.modifiers; mod != 0; mod = mod->u.st.modifiers) {
+ if (!strcmp(mod->u.st.index, name))
+ return 1;
+ }
+
+ return 0;
+}
+
+