Update CQL API documentation a bit
[yaz-moved-to-github.git] / doc / tools.xml
index 4b0d62b..2544316 100644 (file)
@@ -1,6 +1,5 @@
-<!-- $Id: tools.xml,v 1.59 2007-05-04 12:24:15 adam Exp $ -->
  <chapter id="tools"><title>Supporting Tools</title>
  <chapter id="tools"><title>Supporting Tools</title>
-  
+
   <para>
    In support of the service API - primarily the ASN module, which
    provides the pro-grammatic interface to the Z39.50 APDUs, &yaz; contains
   <para>
    In support of the service API - primarily the ASN module, which
    provides the pro-grammatic interface to the Z39.50 APDUs, &yaz; contains
@@ -41,7 +40,7 @@
      </para>
     </note>
     <para>
      </para>
     </note>
     <para>
-     The PQF is defined by the pquery module in the YAZ library. 
+     The PQF is defined by the pquery module in the YAZ library.
      There are two sets of function that have similar behavior. First
      set operates on a PQF parser handle, second set doesn't. First set
      set of functions are more flexible than the second set. Second set
      There are two sets of function that have similar behavior. First
      set operates on a PQF parser handle, second set doesn't. First set
      set of functions are more flexible than the second set. Second set
     <synopsis>
      #include &lt;yaz/pquery.h&gt;
 
     <synopsis>
      #include &lt;yaz/pquery.h&gt;
 
-     YAZ_PQF_Parser yaz_pqf_create (void);
+     YAZ_PQF_Parser yaz_pqf_create(void);
 
 
-     void yaz_pqf_destroy (YAZ_PQF_Parser p);
+     void yaz_pqf_destroy(YAZ_PQF_Parser p);
 
 
-     Z_RPNQuery *yaz_pqf_parse (YAZ_PQF_Parser p, ODR o, const char *qbuf);
+     Z_RPNQuery *yaz_pqf_parse(YAZ_PQF_Parser p, ODR o, const char *qbuf);
 
 
-     Z_AttributesPlusTerm *yaz_pqf_scan (YAZ_PQF_Parser p, ODR o,
+     Z_AttributesPlusTerm *yaz_pqf_scan(YAZ_PQF_Parser p, ODR o,
                           Odr_oid **attributeSetId, const char *qbuf);
 
                           Odr_oid **attributeSetId, const char *qbuf);
 
-
-     int yaz_pqf_error (YAZ_PQF_Parser p, const char **msg, size_t *off);
+     int yaz_pqf_error(YAZ_PQF_Parser p, const char **msg, size_t *off);
     </synopsis>
     <para>
      A PQF parser is created and destructed by functions
     </synopsis>
     <para>
      A PQF parser is created and destructed by functions
@@ -74,7 +72,7 @@
      a Z39.50 RPN Query is returned which is created using ODR stream
      <literal>o</literal>. If parsing failed, a NULL pointer is
      returned.
      a Z39.50 RPN Query is returned which is created using ODR stream
      <literal>o</literal>. If parsing failed, a NULL pointer is
      returned.
-     Function <function>yaz_pqf_scan</function> takes a scan query in 
+     Function <function>yaz_pqf_scan</function> takes a scan query in
      <literal>qbuf</literal>. If parsing was successful, the function
      returns attributes plus term pointer and modifies
      <literal>attributeSetId</literal> to hold attribute set for the
      <literal>qbuf</literal>. If parsing was successful, the function
      returns attributes plus term pointer and modifies
      <literal>attributeSetId</literal> to hold attribute set for the
     <synopsis>
      #include &lt;yaz/pquery.h&gt;
 
     <synopsis>
      #include &lt;yaz/pquery.h&gt;
 
-     Z_RPNQuery *p_query_rpn (ODR o, oid_proto proto, const char *qbuf);
+     Z_RPNQuery *p_query_rpn(ODR o, oid_proto proto, const char *qbuf);
 
 
-     Z_AttributesPlusTerm *p_query_scan (ODR o, oid_proto proto,
+     Z_AttributesPlusTerm *p_query_scan(ODR o, oid_proto proto,
                              Odr_oid **attributeSetP, const char *qbuf);
 
                              Odr_oid **attributeSetP, const char *qbuf);
 
-     int p_query_attset (const char *arg);
+     int p_query_attset(const char *arg);
     </synopsis>
     <para>
      The function <function>p_query_rpn()</function> takes as arguments an
     </synopsis>
     <para>
      The function <function>p_query_rpn()</function> takes as arguments an
     <para>
      If the parse went well, <function>p_query_rpn()</function> returns a
      pointer to a <literal>Z_RPNQuery</literal> structure which can be
     <para>
      If the parse went well, <function>p_query_rpn()</function> returns a
      pointer to a <literal>Z_RPNQuery</literal> structure which can be
-     placed directly into a <literal>Z_SearchRequest</literal>. 
+     placed directly into a <literal>Z_SearchRequest</literal>.
      If parsing failed, due to syntax error, a NULL pointer is returned.
     </para>
     <para>
      If parsing failed, due to syntax error, a NULL pointer is returned.
     </para>
     <para>
     </para>
 
     <para>
     </para>
 
     <para>
-     The @attr operator is followed by an attribute specification 
+     The @attr operator is followed by an attribute specification
      (<literal>attr-spec</literal> above). The specification consists
      of an optional attribute set, an attribute type-value pair and
      a sub-query. The attribute type-value pair is packed in one string:
      (<literal>attr-spec</literal> above). The specification consists
      of an optional attribute set, an attribute type-value pair and
      a sub-query. The attribute type-value pair is packed in one string:
      is used.  This is the only encoding allowed in both versions 2 and 3
      of the Z39.50 standard.
     </para>
      is used.  This is the only encoding allowed in both versions 2 and 3
      of the Z39.50 standard.
     </para>
-    
+
     <sect3 id="PQF-prox">
       <title>Using Proximity Operators with PQF</title>
       <note>
     <sect3 id="PQF-prox">
       <title>Using Proximity Operators with PQF</title>
       <note>
       <para>
         The proximity operator <literal>@prox</literal> is a special
         and more restrictive version of the conjunction operator
       <para>
         The proximity operator <literal>@prox</literal> is a special
         and more restrictive version of the conjunction operator
-        <literal>@and</literal>.  Its semantics are described in 
+        <literal>@and</literal>.  Its semantics are described in
        section 3.7.2 (Proximity) of Z39.50 the standard itself, which
         can be read on-line at
        <ulink url="&url.z39.50.proximity;"/>
        section 3.7.2 (Proximity) of Z39.50 the standard itself, which
         can be read on-line at
        <ulink url="&url.z39.50.proximity;"/>
       <para>
        <screen>
        @or @and bob dylan @set Result-1
       <para>
        <screen>
        @or @and bob dylan @set Result-1
-       
+
        @attr 4=1 @and @attr 1=1 "bob dylan" @attr 1=4 "slow train coming"
        @attr 4=1 @and @attr 1=1 "bob dylan" @attr 1=4 "slow train coming"
-       
+
        @and @attr 2=4 @attr gils 1=2038 -114 @attr 2=2 @attr gils 1=2039 -109
       </screen>
        <note>
        @and @attr 2=4 @attr gils 1=2038 -114 @attr 2=2 @attr gils 1=2039 -109
       </screen>
        <note>
      symbolic language for expressing boolean query structures.
     </para>
 
      symbolic language for expressing boolean query structures.
     </para>
 
-    <para>
-     The EUROPAGATE research project working under the Libraries programme
-     of the European Commission's DG XIII has, amongst other useful tools,
-     implemented a general-purpose CCL parser which produces an output
-     structure that can be trivially converted to the internal RPN
-     representation of &yaz; (The <literal>Z_RPNQuery</literal> structure).
-     Since the CCL utility - along with the rest of the software
-     produced by EUROPAGATE - is made freely available on a liberal
-     license, it is included as a supplement to &yaz;.
-    </para>
-
     <sect3 id="ccl.syntax">
      <title>CCL Syntax</title>
 
     <sect3 id="ccl.syntax">
      <title>CCL Syntax</title>
 
       -- Proximity operator
 
      </screen>
       -- Proximity operator
 
      </screen>
-     
+
      <example id="example.ccl.queries">
       <title>CCL queries</title>
       <para>
        The following queries are all valid:
       </para>
      <example id="example.ccl.queries">
       <title>CCL queries</title>
       <para>
        The following queries are all valid:
       </para>
-      
+
       <screen>
        dylan
       <screen>
        dylan
-       
+
        "bob dylan"
        "bob dylan"
-       
+
        dylan or zimmerman
        dylan or zimmerman
-       
+
        set=1
        set=1
-       
+
        (dylan and bob) or set=1
        (dylan and bob) or set=1
-       
+
+       righttrunc?
+
+       "notrunc?"
+
+       singlechar#mask
+
       </screen>
       <para>
        Assuming that the qualifiers <literal>ti</literal>,
        <literal>au</literal>
        and <literal>date</literal> are defined we may use:
       </para>
       </screen>
       <para>
        Assuming that the qualifiers <literal>ti</literal>,
        <literal>au</literal>
        and <literal>date</literal> are defined we may use:
       </para>
-      
+
       <screen>
        ti=self portrait
       <screen>
        ti=self portrait
-       
+
        au=(bob dylan and slow train coming)
 
        date>1980 and (ti=((self portrait)))
        au=(bob dylan and slow train coming)
 
        date>1980 and (ti=((self portrait)))
-       
+
       </screen>
      </example>
       </screen>
      </example>
-     
+
     </sect3>
     <sect3 id="ccl.qualifiers">
      <title>CCL Qualifiers</title>
     </sect3>
     <sect3 id="ccl.qualifiers">
      <title>CCL Qualifiers</title>
-     
+
      <para>
       Qualifiers are used to direct the search to a particular searchable
       index, such as title (ti) and author indexes (au). The CCL standard
      <para>
       Qualifiers are used to direct the search to a particular searchable
       index, such as title (ti) and author indexes (au). The CCL standard
       <para>
        A qualifier specification is of the form:
       </para>
       <para>
        A qualifier specification is of the form:
       </para>
-      
+
       <para>
       <para>
-       <replaceable>qualifier-name</replaceable>  
+       <replaceable>qualifier-name</replaceable>
        [<replaceable>attributeset</replaceable><literal>,</literal>]<replaceable>type</replaceable><literal>=</literal><replaceable>val</replaceable>
        [<replaceable>attributeset</replaceable><literal>,</literal>]<replaceable>type</replaceable><literal>=</literal><replaceable>val</replaceable>
-       [<replaceable>attributeset</replaceable><literal>,</literal>]<replaceable>type</replaceable><literal>=</literal><replaceable>val</replaceable> ...      
+       [<replaceable>attributeset</replaceable><literal>,</literal>]<replaceable>type</replaceable><literal>=</literal><replaceable>val</replaceable> ...
       </para>
       </para>
-      
+
       <para>
        where <replaceable>qualifier-name</replaceable> is the name of the
        qualifier to be used (eg. <literal>ti</literal>),
       <para>
        where <replaceable>qualifier-name</replaceable> is the name of the
        qualifier to be used (eg. <literal>ti</literal>),
        <replaceable>val</replaceable> is attribute value.
        The <replaceable>type</replaceable> can be specified as an
        integer or as it be specified either as a single-letter:
        <replaceable>val</replaceable> is attribute value.
        The <replaceable>type</replaceable> can be specified as an
        integer or as it be specified either as a single-letter:
-       <literal>u</literal> for use, 
+       <literal>u</literal> for use,
        <literal>r</literal> for relation,<literal>p</literal> for position,
        <literal>s</literal> for structure,<literal>t</literal> for truncation
        or <literal>c</literal> for completeness.
        <literal>r</literal> for relation,<literal>p</literal> for position,
        <literal>s</literal> for structure,<literal>t</literal> for truncation
        or <literal>c</literal> for completeness.
        </table>
       </para>
       <para>
        </table>
       </para>
       <para>
-       Refer to the complete
+       Refer to <xref linkend="bib1"/> or the complete
        <ulink url="&url.z39.50.attset.bib1;">list of Bib-1 attributes</ulink>
       </para>
       <para>
        <ulink url="&url.z39.50.attset.bib1;">list of Bib-1 attributes</ulink>
       </para>
       <para>
-       It is also possible to specify non-numeric attribute values, 
+       It is also possible to specify non-numeric attribute values,
        which are used in combination with certain types.
        The special combinations are:
        which are used in combination with certain types.
        The special combinations are:
-       
+
        <table id="ccl.special.attribute.combos">
        <title>Special attribute combos</title>
        <tgroup cols="2">
        <table id="ccl.special.attribute.combos">
        <title>Special attribute combos</title>
        <tgroup cols="2">
            This does not set the structure at all.
           </entry>
          </row>
            This does not set the structure at all.
           </entry>
          </row>
-         
+
          <row><entry><literal>s=ol</literal></entry><entry>
            Each token in the term is ORed. (or-list).
            This does not set the structure at all.
           </entry>
          </row>
          <row><entry><literal>s=ol</literal></entry><entry>
            Each token in the term is ORed. (or-list).
            This does not set the structure at all.
           </entry>
          </row>
-         
+
+         <row><entry><literal>s=ag</literal></entry><entry>
+           Tokens that appears as phrases (with blank in them) gets
+           structure phrase attached. Tokens that appers as words
+           gets structure phrase attached. Phrases and words are
+           ANDed. This is a variant of s=al and s=pw, with the main
+           difference that words are not split (with operator AND)
+           but instead kept in one RPN token. This facility appeared
+           in YAZ 4.2.38.
+          </entry>
+         </row>
+
          <row><entry><literal>r=o</literal></entry><entry>
            Allows ranges and the operators greather-than, less-than, ...
            equals.
            This sets Bib-1 relation attribute accordingly (relation
            ordered). A query construct is only treated as a range if
            dash is used and that is surrounded by white-space. So
          <row><entry><literal>r=o</literal></entry><entry>
            Allows ranges and the operators greather-than, less-than, ...
            equals.
            This sets Bib-1 relation attribute accordingly (relation
            ordered). A query construct is only treated as a range if
            dash is used and that is surrounded by white-space. So
-           <literal>-1980</literal> is treated as term 
+           <literal>-1980</literal> is treated as term
            <literal>"-1980"</literal> not <literal>&lt;= 1980</literal>.
            If <literal>- 1980</literal> is used, however, that is
            treated as a range.
           </entry>
          </row>
            <literal>"-1980"</literal> not <literal>&lt;= 1980</literal>.
            If <literal>- 1980</literal> is used, however, that is
            treated as a range.
           </entry>
          </row>
-         
+
          <row><entry><literal>r=r</literal></entry><entry>
            Similar to <literal>r=o</literal> but assumes that terms
            are non-negative (not prefixed with <literal>-</literal>).
          <row><entry><literal>r=r</literal></entry><entry>
            Similar to <literal>r=o</literal> but assumes that terms
            are non-negative (not prefixed with <literal>-</literal>).
            <literal>r=r</literal> is available in YAZ 2.0.24 or later.
           </entry>
          </row>
            <literal>r=r</literal> is available in YAZ 2.0.24 or later.
           </entry>
          </row>
-         
+
          <row><entry><literal>t=l</literal></entry><entry>
            Allows term to be left-truncated.
            If term is of the form <literal>?x</literal>, the resulting
            Type-1 term is <literal>x</literal> and truncation is left.
           </entry>
          </row>
          <row><entry><literal>t=l</literal></entry><entry>
            Allows term to be left-truncated.
            If term is of the form <literal>?x</literal>, the resulting
            Type-1 term is <literal>x</literal> and truncation is left.
           </entry>
          </row>
-         
+
          <row><entry><literal>t=r</literal></entry><entry>
            Allows term to be right-truncated.
            If term is of the form <literal>x?</literal>, the resulting
            Type-1 term is <literal>x</literal> and truncation is right.
           </entry>
          </row>
          <row><entry><literal>t=r</literal></entry><entry>
            Allows term to be right-truncated.
            If term is of the form <literal>x?</literal>, the resulting
            Type-1 term is <literal>x</literal> and truncation is right.
           </entry>
          </row>
-         
+
          <row><entry><literal>t=n</literal></entry><entry>
            If term is does not include <literal>?</literal>, the
            truncation attribute is set to none (100).
           </entry>
          </row>
          <row><entry><literal>t=n</literal></entry><entry>
            If term is does not include <literal>?</literal>, the
            truncation attribute is set to none (100).
           </entry>
          </row>
-         
+
          <row><entry><literal>t=b</literal></entry><entry>
            Allows term to be both left&amp;right truncated.
            If term is of the form <literal>?x?</literal>, the
          <row><entry><literal>t=b</literal></entry><entry>
            Allows term to be both left&amp;right truncated.
            If term is of the form <literal>?x?</literal>, the
            set to both left&amp;right.
           </entry>
          </row>
            set to both left&amp;right.
           </entry>
          </row>
+
+         <row><entry><literal>t=x</literal></entry><entry>
+           Allows masking anywhere in a term, thus fully supporting
+           # (mask one character) and ? (zero or more of any).
+           If masking is used, trunction is set to 102 (regexp-1 in term)
+           and the term is converted accordingly to a regular expression.
+          </entry>
+         </row>
+
+         <row><entry><literal>t=z</literal></entry><entry>
+           Allows masking anywhere in a term, thus fully supporting
+           # (mask one character) and ? (zero or more of any).
+           If masking is used, trunction is set to 104 (Z39.58 in term)
+           and the term is converted accordingly to Z39.58 masking term -
+           actually the same truncation as CCL itself.
+          </entry>
+         </row>
+
         </tbody>
        </tgroup>
        </table>
         </tbody>
        </tgroup>
        </table>
        <para>
        Consider the following definition:
        </para>
        <para>
        Consider the following definition:
        </para>
-       
+
        <screen>
        ti       u=4 s=1
        au       u=1 s=1
        <screen>
        ti       u=4 s=1
        au       u=1 s=1
        date     u=30 r=o
       </screen>
        <para>
        date     u=30 r=o
       </screen>
        <para>
-       <literal>ti</literal> and <literal>au</literal> both set 
+       <literal>ti</literal> and <literal>au</literal> both set
        structure attribute to phrase (s=1).
        <literal>ti</literal>
        sets the use-attribute to 4. <literal>au</literal> sets the
        structure attribute to phrase (s=1).
        <literal>ti</literal>
        sets the use-attribute to 4. <literal>au</literal> sets the
        </para>
        <para>
        You can combine attributes. To Search for "ranked title" you
        </para>
        <para>
        You can combine attributes. To Search for "ranked title" you
-       can do 
+       can do
        <screen>
         ti,ranked=knuth computer
        </screen>
        <screen>
         ti,ranked=knuth computer
        </screen>
        A qualifier alias is of the form:
       </para>
       <para>
        A qualifier alias is of the form:
       </para>
       <para>
-       <replaceable>q</replaceable>  
+       <replaceable>q</replaceable>
        <replaceable>q1</replaceable> <replaceable>q2</replaceable> ..
       </para>
       <para>
        which declares <replaceable>q</replaceable> to
        <replaceable>q1</replaceable> <replaceable>q2</replaceable> ..
       </para>
       <para>
        which declares <replaceable>q</replaceable> to
-       be an alias for <replaceable>q1</replaceable>, 
+       be an alias for <replaceable>q1</replaceable>,
        <replaceable>q2</replaceable>... such that the CCL
        query <replaceable>q=x</replaceable> is equivalent to
        <replaceable>q1=x or q2=x or ...</replaceable>.
        <replaceable>q2</replaceable>... such that the CCL
        query <replaceable>q=x</replaceable> is equivalent to
        <replaceable>q1=x or q2=x or ...</replaceable>.
         </row>
         <row>
          <entry>case</entry>
         </row>
         <row>
          <entry>case</entry>
-         <entry>Specificies if CCL operatores and qualifiers should be
-          compared with case sensitivity or not. Specify 0 for
-          case sensitive; 1 for case insensitive.</entry>
-         <entry><literal>0</literal></entry>
+         <entry>Specifies if CCL operators and qualifiers should be
+          compared with case sensitivity or not. Specify 1 for
+          case sensitive; 0 for case insensitive.</entry>
+         <entry><literal>1</literal></entry>
         </row>
 
         <row>
         </row>
 
         <row>
       To parse a simple string with a FIND query use the function
      </para>
      <screen>
       To parse a simple string with a FIND query use the function
      </para>
      <screen>
-struct ccl_rpn_node *ccl_find_str (CCL_bibset bibset, const char *str,
-                                   int *error, int *pos);
+struct ccl_rpn_node *ccl_find_str(CCL_bibset bibset, const char *str,
+                                  int *error, int *pos);
      </screen>
      <para>
       which takes the CCL profile (<literal>bibset</literal>) and query
      </screen>
      <para>
       which takes the CCL profile (<literal>bibset</literal>) and query
@@ -966,7 +988,7 @@ struct ccl_rpn_node *ccl_find_str (CCL_bibset bibset, const char *str,
     </para>
     <tip>
      <para>
     </para>
     <tip>
      <para>
-      If you are new to CQL, read the 
+      If you are new to CQL, read the
       <ulink url="&url.cql.intro;">Gentle Introduction</ulink>.
      </para>
     </tip>
       <ulink url="&url.cql.intro;">Gentle Introduction</ulink>.
      </para>
     </tip>
@@ -1049,7 +1071,7 @@ int cql_parser_stdio(CQL_parser cp, FILE *f);
       uses a <literal>FILE</literal> handle which is opened for reading.
      </para>
     </sect3>
       uses a <literal>FILE</literal> handle which is opened for reading.
      </para>
     </sect3>
-    
+
     <sect3 id="cql.tree"><title>CQL tree</title>
      <para>
       The the query string is valid, the CQL parser
     <sect3 id="cql.tree"><title>CQL tree</title>
      <para>
       The the query string is valid, the CQL parser
@@ -1064,12 +1086,13 @@ struct cql_node *cql_parser_result(CQL_parser cp);
       a pointer to the root node of the resulting tree.
      </para>
      <para>
       a pointer to the root node of the resulting tree.
      </para>
      <para>
-      Each node in a CQL tree is represented by a 
+      Each node in a CQL tree is represented by a
       <literal>struct cql_node</literal>.
       It is defined as follows:
       <synopsis>
 #define CQL_NODE_ST 1
 #define CQL_NODE_BOOL 2
       <literal>struct cql_node</literal>.
       It is defined as follows:
       <synopsis>
 #define CQL_NODE_ST 1
 #define CQL_NODE_BOOL 2
+#define CQL_NODE_SORT 3
 struct cql_node {
     int which;
     union {
 struct cql_node {
     int which;
     union {
@@ -1087,10 +1110,17 @@ struct cql_node {
             struct cql_node *right;
             struct cql_node *modifiers;
         } boolean;
             struct cql_node *right;
             struct cql_node *modifiers;
         } boolean;
+        struct {
+            char *index;
+            struct cql_node *next;
+            struct cql_node *modifiers;
+            struct cql_node *search;
+        } sort;
     } u;
 };
       </synopsis>
     } u;
 };
       </synopsis>
-      There are two node types: search term (ST) and boolean (BOOL).
+      There are three node types: search term (ST), boolean (BOOL)
+      and sortby (SORT).
       A modifier is treated as a search term too.
      </para>
      <para>
       A modifier is treated as a search term too.
      </para>
      <para>
@@ -1135,8 +1165,8 @@ struct cql_node {
      </para>
 
      <para>
      </para>
 
      <para>
-      The boolean node represents both <literal>and</literal>,
-      <literal>or</literal>, not as well as
+      The boolean node represents <literal>and</literal>,
+      <literal>or</literal>, <literal>not</literal> +
       proximity.
       <itemizedlist>
        <listitem>
       proximity.
       <itemizedlist>
        <listitem>
@@ -1153,12 +1183,16 @@ struct cql_node {
       </itemizedlist>
      </para>
 
       </itemizedlist>
      </para>
 
+     <para>
+      The sort node represents both the SORTBY clause.
+     </para>
+
     </sect3>
     <sect3 id="cql.to.pqf"><title>CQL to PQF conversion</title>
      <para>
       Conversion to PQF (and Z39.50 RPN) is tricky by the fact
       that the resulting RPN depends on the Z39.50 target
     </sect3>
     <sect3 id="cql.to.pqf"><title>CQL to PQF conversion</title>
      <para>
       Conversion to PQF (and Z39.50 RPN) is tricky by the fact
       that the resulting RPN depends on the Z39.50 target
-      capabilities (combinations of supported attributes). 
+      capabilities (combinations of supported attributes).
       In addition, the CQL and SRU operates on index prefixes
       (URI or strings), whereas the RPN uses Object Identifiers
       for attribute sets.
       In addition, the CQL and SRU operates on index prefixes
       (URI or strings), whereas the RPN uses Object Identifiers
       for attribute sets.
@@ -1176,7 +1210,7 @@ void cql_transform_close(cql_transform_t ct);
       either an already open FILE or from a filename respectively.
      </para>
      <para>
       either an already open FILE or from a filename respectively.
      </para>
      <para>
-      The handle is destroyed by <function>cql_transform_close</function> 
+      The handle is destroyed by <function>cql_transform_close</function>
       in which case no further reference of the handle is allowed.
      </para>
      <para>
       in which case no further reference of the handle is allowed.
      </para>
      <para>
@@ -1186,7 +1220,7 @@ void cql_transform_close(cql_transform_t ct);
 int cql_transform_buf(cql_transform_t ct,
                       struct cql_node *cn, char *out, int max);
       </synopsis>
 int cql_transform_buf(cql_transform_t ct,
                       struct cql_node *cn, char *out, int max);
       </synopsis>
-      This function converts the CQL tree <literal>cn</literal> 
+      This function converts the CQL tree <literal>cn</literal>
       using handle <literal>ct</literal>.
       For the resulting PQF, you supply a buffer <literal>out</literal>
       which must be able to hold at at least <literal>max</literal>
       using handle <literal>ct</literal>.
       For the resulting PQF, you supply a buffer <literal>out</literal>
       which must be able to hold at at least <literal>max</literal>
@@ -1239,7 +1273,7 @@ int cql_transform_FILE(cql_transform_t ct,
     <sect3 id="cql.to.rpn">
      <title>Specification of CQL to RPN mappings</title>
      <para>
     <sect3 id="cql.to.rpn">
      <title>Specification of CQL to RPN mappings</title>
      <para>
-      The file supplied to functions 
+      The file supplied to functions
       <function>cql_transform_open_FILE</function>,
       <function>cql_transform_open_fname</function> follows
       a structure found in many Unix utilities.
       <function>cql_transform_open_FILE</function>,
       <function>cql_transform_open_fname</function> follows
       a structure found in many Unix utilities.
@@ -1277,7 +1311,7 @@ int cql_transform_FILE(cql_transform_t ct,
         </term>
         <listitem>
          <para>
         </term>
         <listitem>
          <para>
-          This pattern is invoked when a CQL index, such as 
+          This pattern is invoked when a CQL index, such as
           dc.title is converted. <replaceable>set</replaceable>
           and <replaceable>name</replaceable> are the context set and index
           name respectively.
           dc.title is converted. <replaceable>set</replaceable>
           and <replaceable>name</replaceable> are the context set and index
           name respectively.
@@ -1291,7 +1325,7 @@ int cql_transform_FILE(cql_transform_t ct,
           If this pattern is not defined, the mapping will fail.
          </para>
          <para>
           If this pattern is not defined, the mapping will fail.
          </para>
          <para>
-          The pattern, 
+          The pattern,
           <literal>index.</literal><replaceable>set</replaceable><literal>.*</literal>
           is used when no other index pattern is matched.
         </para>
           <literal>index.</literal><replaceable>set</replaceable><literal>.*</literal>
           is used when no other index pattern is matched.
         </para>
@@ -1356,7 +1390,7 @@ int cql_transform_FILE(cql_transform_t ct,
          <para>
           This pattern specifies how a CQL structure is mapped to RPN.
           Note that this CQL pattern is somewhat to similar to
          <para>
           This pattern specifies how a CQL structure is mapped to RPN.
           Note that this CQL pattern is somewhat to similar to
-          CQL pattern <literal>relation</literal>. 
+          CQL pattern <literal>relation</literal>.
           The <replaceable>type</replaceable> is a CQL relation.
          </para>
          <para>
           The <replaceable>type</replaceable> is a CQL relation.
          </para>
          <para>
@@ -1391,7 +1425,7 @@ int cql_transform_FILE(cql_transform_t ct,
         <listitem>
          <para>
           This specification defines a CQL context set for a given prefix.
         <listitem>
          <para>
           This specification defines a CQL context set for a given prefix.
-          The value on the right hand side is the URI for the set - 
+          The value on the right hand side is the URI for the set -
           <emphasis>not</emphasis> RPN. All prefixes used in
           index patterns must be defined this way.
          </para>
           <emphasis>not</emphasis> RPN. All prefixes used in
           index patterns must be defined this way.
          </para>
@@ -1424,7 +1458,7 @@ int cql_transform_FILE(cql_transform_t ct,
        index.cql.serverChoice = 1=1016
        index.dc.title         = 1=4
        index.dc.subject       = 1=21
        index.cql.serverChoice = 1=1016
        index.dc.title         = 1=4
        index.dc.subject       = 1=21
-  
+
        relation.<             = 2=1
        relation.eq            = 2=3
        relation.scr           = 2=3
        relation.<             = 2=1
        relation.eq            = 2=3
        relation.scr           = 2=3
@@ -1519,7 +1553,7 @@ int cql_transform_FILE(cql_transform_t ct,
       containing XCQL).
       <synopsis>
 int cql_to_xml_buf(struct cql_node *cn, char *out, int max);
       containing XCQL).
       <synopsis>
 int cql_to_xml_buf(struct cql_node *cn, char *out, int max);
-void cql_to_xml(struct cql_node *cn, 
+void cql_to_xml(struct cql_node *cn,
                 void (*pr)(const char *buf, void *client_data),
                 void *client_data);
 void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
                 void (*pr)(const char *buf, void *client_data),
                 void *client_data);
 void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
@@ -1535,33 +1569,57 @@ void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
       a file.
      </para>
     </sect3>
       a file.
      </para>
     </sect3>
+    <sect3 id="rpn.to.cql">
+     <title>PQF to CQL conversion</title>
+     <para>
+      Conversion from PQF to CQL is offered by the two functions shown
+      below. The former uses a generic stream for result. The latter
+      puts result in a WRBUF (string container).
+     <synopsis>
+#include &lt;yaz/rpn2cql.h>
+
+int cql_transform_rpn2cql_stream(cql_transform_t ct,
+                                 void (*pr)(const char *buf, void *client_data),
+                                 void *client_data,
+                                 Z_RPNQuery *q);
+
+int cql_transform_rpn2cql_wrbuf(cql_transform_t ct,
+                                WRBUF w,
+                                Z_RPNQuery *q);
+      </synopsis>
+      The configuration is the same as used in CQL to PQF conversions.
+     </para>
+    </sect3>
    </sect2>
   </sect1>
   <sect1 id="tools.oid"><title>Object Identifiers</title>
 
    <para>
     The basic YAZ representation of an OID is an array of integers,
    </sect2>
   </sect1>
   <sect1 id="tools.oid"><title>Object Identifiers</title>
 
    <para>
     The basic YAZ representation of an OID is an array of integers,
-    terminated with the value -1. There is a <literal>typedef</literal>
-    of this integer to <literal>Odr_oid</literal> but this is not consistenly
-    used everywhere.
+    terminated with the value -1. This integer is of type
+    <literal>Odr_oid</literal>.
+   </para>
+   <para>
+    Fundamental OID operations and the type <literal>Odr_oid</literal>
+    are defined in <filename>yaz/oid_util.h</filename>.
    </para>
    <para>
    </para>
    <para>
-    An OID can either be declared as a automatic variable or we can
-    allocated using the ODR/NMEM memory utilities. It's
+    An OID can either be declared as a automatic variable or it can
+    allocated using the memory utilities or ODR/NMEM. It's
     guaranteed that an OID can fit in <literal>OID_SIZE</literal> integers.
    </para>
    <example id="tools.oid.bib1.1"><title>Create OID on stack</title>
     <para>
      We can create an OID for the Bib-1 attribute set with:
      <screen>
     guaranteed that an OID can fit in <literal>OID_SIZE</literal> integers.
    </para>
    <example id="tools.oid.bib1.1"><title>Create OID on stack</title>
     <para>
      We can create an OID for the Bib-1 attribute set with:
      <screen>
-      int bib1[OID_SIZE];
-      myoid[0] = 1;
-      myoid[1] = 2;
-      myoid[2] = 840;
-      myoid[3] = 10003;
-      myoid[4] = 3;
-      myoid[5] = 1;
-      myoid[6] = -1;
+      Odr_oid bib1[OID_SIZE];
+      bib1[0] = 1;
+      bib1[1] = 2;
+      bib1[2] = 840;
+      bib1[3] = 10003;
+      bib1[4] = 3;
+      bib1[5] = 1;
+      bib1[6] = -1;
      </screen>
     </para>
    </example>
      </screen>
     </para>
    </example>
@@ -1569,14 +1627,15 @@ void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
     And OID may also be filled from a string-based representation using
     dots (.). This is achieved by function
     <screen>
     And OID may also be filled from a string-based representation using
     dots (.). This is achieved by function
     <screen>
-     int oid_dotstring_to_oid(const char *name, int *oid);
+     int oid_dotstring_to_oid(const char *name, Odr_oid *oid);
     </screen>
     </screen>
+    This functions returns 0 if name could be converted; -1 otherwise.
    </para>
    <example id="tools.oid.bib1.2"><title>Using oid_oiddotstring_to_oid</title>
     <para>
    </para>
    <example id="tools.oid.bib1.2"><title>Using oid_oiddotstring_to_oid</title>
     <para>
-     We can create the Bib-1 attribute set OID easier with:
+     We can fill the Bib-1 attribute set OID easier with:
      <screen>
      <screen>
-      int bib1[OID_SIZE];
+      Odr_oid bib1[OID_SIZE];
       oid_oiddotstring_to_oid("1.2.840.10003.3.1", bib1);
      </screen>
    </para>
       oid_oiddotstring_to_oid("1.2.840.10003.3.1", bib1);
      </screen>
    </para>
@@ -1604,7 +1663,7 @@ void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
    <para>
     The function
     <screen>
    <para>
     The function
     <screen>
-     char *oid_oid_to_dotstring(const int *oid, char *oidbuf)
+     char *oid_oid_to_dotstring(const Odr_oid *oid, char *oidbuf)
     </screen>
     does the reverse of <function>oid_oiddotstring_to_oid</function>. It
     converts an OID to the string-based representation using dots.
     </screen>
     does the reverse of <function>oid_oiddotstring_to_oid</function>. It
     converts an OID to the string-based representation using dots.
@@ -1620,17 +1679,17 @@ void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
      Odr_oid *odr_oiddup(ODR odr, const Odr_oid *o);
     </screen>
    </para>
      Odr_oid *odr_oiddup(ODR odr, const Odr_oid *o);
     </screen>
    </para>
-   
+
    <para>
     OIDs can be compared with <function>oid_oidcmp</function> which returns
     zero if the two OIDs provided are identical; non-zero otherwise.
    </para>
    <para>
     OIDs can be compared with <function>oid_oidcmp</function> which returns
     zero if the two OIDs provided are identical; non-zero otherwise.
    </para>
+
    <sect2 id="tools.oid.database"><title>OID database</title>
     <para>
      From YAZ version 3 and later, the oident system has been replaced
      by an OID database. OID database is a misnomer .. the old odient
    <sect2 id="tools.oid.database"><title>OID database</title>
     <para>
      From YAZ version 3 and later, the oident system has been replaced
      by an OID database. OID database is a misnomer .. the old odient
-     was a database system too.
+     system was also a database.
     </para>
     <para>
      The OID database is really just a map between named Object Identifiers
     </para>
     <para>
      The OID database is really just a map between named Object Identifiers
@@ -1638,21 +1697,21 @@ void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
      convert from string to OID or other way around.
     </para>
     <para>
      convert from string to OID or other way around.
     </para>
     <para>
-     Unfortunately, whenever we supply a string we must also specify the 
+     Unfortunately, whenever we supply a string we must also specify the
      <emphasis>OID class</emphasis>. The class is necessary because some
      strings correspond to multiple OIDs. An example of such a string is
      <emphasis>OID class</emphasis>. The class is necessary because some
      strings correspond to multiple OIDs. An example of such a string is
-     <literal>Bib-1</literal> which may either be an attribute-set 
+     <literal>Bib-1</literal> which may either be an attribute-set
      or a diagnostic-set.
     </para>
     <para>
      or a diagnostic-set.
     </para>
     <para>
-     Applications using the YAZ database should include 
-     <filename>yaz/yaz_db.h</filename>.
+     Applications using the YAZ database should include
+     <filename>yaz/oid_db.h</filename>.
     </para>
     <para>
      A YAZ database handle is of type <literal>yaz_oid_db_t</literal>.
      Actually that's a pointer. You need not think deal with that.
      YAZ has a built-in database which can be considered "constant" for
     </para>
     <para>
      A YAZ database handle is of type <literal>yaz_oid_db_t</literal>.
      Actually that's a pointer. You need not think deal with that.
      YAZ has a built-in database which can be considered "constant" for
-     most purposes. 
+     most purposes.
      We can get hold that by using function <function>yaz_oid_std</function>.
     </para>
     <para>
      We can get hold that by using function <function>yaz_oid_std</function>.
     </para>
     <para>
@@ -1671,7 +1730,7 @@ void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
       We can create an OID for the Bib-1 attribute set on the ODR stream
       odr with:
      <screen>
       We can create an OID for the Bib-1 attribute set on the ODR stream
       odr with:
      <screen>
-        Odr_oid *bib1 = 
+        Odr_oid *bib1 =
          yaz_string_to_oid_odr(yaz_oid_std(), CLASS_ATTSET, "Bib-1", odr);
       </screen>
       This is more complex than using <function>odr_getoidbystr</function>.
          yaz_string_to_oid_odr(yaz_oid_std(), CLASS_ATTSET, "Bib-1", odr);
       </screen>
       This is more complex than using <function>odr_getoidbystr</function>.
@@ -1679,15 +1738,21 @@ void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
       string (here Bib-1) is supplied by a user or configuration.
      </para>
     </example>
       string (here Bib-1) is supplied by a user or configuration.
      </para>
     </example>
-     
+
+   </sect2>
+   <sect2 id="tools.oid.std"><title>Standard OIDs</title>
+
     <para>
      All the object identifers in the standard OID database as returned
      by <function>yaz_oid_std</function> can referenced directly in a
     <para>
      All the object identifers in the standard OID database as returned
      by <function>yaz_oid_std</function> can referenced directly in a
-     program. Each constant OID is prefixed with <literal>yaz_oid_</literal> -
+     program as a constant OID.
+     Each constant OID is prefixed with <literal>yaz_oid_</literal> -
      followed by OID class (lowercase) - then by OID name (normalized and
      lowercase).
     </para>
     <para>
      followed by OID class (lowercase) - then by OID name (normalized and
      lowercase).
     </para>
     <para>
+     See <xref linkend="list-oids"/> for list of all object identifiers
+     built into YAZ.
      These are declared in <filename>yaz/oid_std.h</filename> but are
      included by <filename>yaz/oid_db.h</filename> as well.
     </para>
      These are declared in <filename>yaz/oid_std.h</filename> but are
      included by <filename>yaz/oid_db.h</filename> as well.
     </para>
@@ -1702,265 +1767,6 @@ void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
      </para>
     </example>
    </sect2>
      </para>
     </example>
    </sect2>
-
-   <sect2 id="tools.oid.oident"><title>OID oident</title>
-
-   <note>
-    <para>
-     The oident utility has been removed from YAZ version 3. This
-     sub section only applies to YAZ version 2.
-    </para>
-   </note>
-
-   <para>
-    The OID module provides a higher-level representation of the
-    family of object identifiers which describe the Z39.50 protocol and its
-    related objects. The definition of the module interface is given in
-    the <filename>oid.h</filename> file.
-   </para>
-
-   <para>
-    The interface is mainly based on the <literal>oident</literal> structure.
-    The definition of this structure looks like this:
-   </para>
-
-   <screen>
-typedef struct oident
-{
-    oid_proto proto;
-    oid_class oclass;
-    oid_value value;
-    int oidsuffix[OID_SIZE];
-    char *desc;
-} oident;
-   </screen>
-
-   <para>
-    The proto field takes one of the values
-   </para>
-
-   <screen>
-    PROTO_Z3950
-    PROTO_GENERAL
-   </screen>
-
-   <para>
-    Use <literal>PROTO_Z3950</literal> for Z39.50 Object Identifers,
-    <literal>PROTO_GENERAL</literal> for other types (such as
-    those associated with ILL).
-   </para>
-   <para>
-
-    The oclass field takes one of the values
-   </para>
-
-   <screen>
-    CLASS_APPCTX
-    CLASS_ABSYN
-    CLASS_ATTSET
-    CLASS_TRANSYN
-    CLASS_DIAGSET
-    CLASS_RECSYN
-    CLASS_RESFORM
-    CLASS_ACCFORM
-    CLASS_EXTSERV
-    CLASS_USERINFO
-    CLASS_ELEMSPEC
-    CLASS_VARSET
-    CLASS_SCHEMA
-    CLASS_TAGSET
-    CLASS_GENERAL
-   </screen>
-
-   <para>
-    corresponding to the OID classes defined by the Z39.50 standard.
-
-    Finally, the value field takes one of the values
-   </para>
-
-   <screen>
-    VAL_APDU
-    VAL_BER
-    VAL_BASIC_CTX
-    VAL_BIB1
-    VAL_EXP1
-    VAL_EXT1
-    VAL_CCL1
-    VAL_GILS
-    VAL_WAIS
-    VAL_STAS
-    VAL_DIAG1
-    VAL_ISO2709
-    VAL_UNIMARC
-    VAL_INTERMARC
-    VAL_CCF
-    VAL_USMARC
-    VAL_UKMARC
-    VAL_NORMARC
-    VAL_LIBRISMARC
-    VAL_DANMARC
-    VAL_FINMARC
-    VAL_MAB
-    VAL_CANMARC
-    VAL_SBN
-    VAL_PICAMARC
-    VAL_AUSMARC
-    VAL_IBERMARC
-    VAL_EXPLAIN
-    VAL_SUTRS
-    VAL_OPAC
-    VAL_SUMMARY
-    VAL_GRS0
-    VAL_GRS1
-    VAL_EXTENDED
-    VAL_RESOURCE1
-    VAL_RESOURCE2
-    VAL_PROMPT1
-    VAL_DES1
-    VAL_KRB1
-    VAL_PRESSET
-    VAL_PQUERY
-    VAL_PCQUERY
-    VAL_ITEMORDER
-    VAL_DBUPDATE
-    VAL_EXPORTSPEC
-    VAL_EXPORTINV
-    VAL_NONE
-    VAL_SETM
-    VAL_SETG
-    VAL_VAR1
-    VAL_ESPEC1
-   </screen>
-
-   <para>
-    again, corresponding to the specific OIDs defined by the standard.
-    Refer to the
-    <ulink url="&url.z39.50.oids;">
-     Registry of Z39.50 Object Identifiers</ulink> for the
-     whole list.
-   </para>
-
-   <para>
-    The desc field contains a brief, mnemonic name for the OID in question.
-   </para>
-
-   <para>
-    The function
-   </para>
-
-   <screen>
-    struct oident *oid_getentbyoid(int *o);
-   </screen>
-
-   <para>
-    takes as argument an OID, and returns a pointer to a static area
-    containing an <literal>oident</literal> structure. You typically use
-    this function when you receive a PDU containing an OID, and you wish
-    to branch out depending on the specific OID value.
-   </para>
-
-   <para>
-    The function
-   </para>
-
-   <screen>
-    int *oid_ent_to_oid(struct oident *ent, int *dst);
-   </screen>
-
-   <para>
-    Takes as argument an <literal>oident</literal> structure - in which
-    the <literal>proto</literal>, <literal>oclass</literal>/, and
-    <literal>value</literal> fields are assumed to be set correctly -
-    and returns a pointer to a the buffer as given by <literal>dst</literal>
-    containing the base
-    representation of the corresponding OID. The function returns
-    NULL and the array dst is unchanged if a mapping couldn't place.
-    The array <literal>dst</literal> should be at least of size
-    <literal>OID_SIZE</literal>.
-   </para>
-   <para>
-
-    The <function>oid_ent_to_oid()</function> function can be used whenever
-    you need to prepare a PDU containing one or more OIDs. The separation of
-    the <literal>protocol</literal> element from the remainder of the
-    OID-description makes it simple to write applications that can
-    communicate with either Z39.50 or OSI SR-based applications.
-   </para>
-
-   <para>
-    The function
-   </para>
-
-   <screen>
-    oid_value oid_getvalbyname(const char *name);
-   </screen>
-
-   <para>
-    takes as argument a mnemonic OID name, and returns the
-    <literal>/value</literal> field of the first entry in the database that 
-    contains the given name in its <literal>desc</literal> field.
-   </para>
-
-   <para>
-    Three utility functions are provided for translating OIDs'
-    symbolic names (e.g. <literal>Usmarc</literal> into OID structures
-    (int arrays) and strings containing the OID in dotted notation
-    (e.g. <literal>1.2.840.10003.9.5.1</literal>).  They are:
-   </para>
-
-   <screen>
-    int *oid_name_to_oid(oid_class oclass, const char *name, int *oid);
-    char *oid_to_dotstring(const int *oid, char *oidbuf);
-    char *oid_name_to_dotstring(oid_class oclass, const char *name, char *oidbuf);
-   </screen>
-
-   <para>
-    <literal>oid_name_to_oid()</literal>
-     translates the specified symbolic <literal>name</literal>,
-     interpreted as being of class <literal>oclass</literal>.  (The
-     class must be specified as many symbolic names exist within
-     multiple classes - for example, <literal>Zthes</literal> is the
-     symbolic name of an attribute set, a schema and a tag-set.)  The
-     sequence of integers representing the OID is written into the
-     area <literal>oid</literal> provided by the caller; it is the
-     caller's responsibility to ensure that this area is large enough
-     to contain the translated OID.  As a convenience, the address of
-     the buffer (i.e. the value of <literal>oid</literal>) is
-     returned.
-   </para>
-   <para>
-    <literal>oid_to_dotstring()</literal>
-    Translates the int-array <literal>oid</literal> into a dotted
-    string which is written into the area <literal>oidbuf</literal>
-    supplied by the caller; it is the caller's responsibility to
-    ensure that this area is large enough.  The address of the buffer
-    is returned.
-   </para>
-   <para>
-    <literal>oid_name_to_dotstring()</literal>
-    combines the previous two functions to derive a dotted string
-    representing the OID specified by <literal>oclass</literal> and
-    <literal>name</literal>, writing it into the buffer passed as
-    <literal>oidbuf</literal> and returning its address.
-   </para>
-
-   <note>
-    <para>
-     The OID module has been criticized - and perhaps rightly so
-     - for needlessly abstracting the
-     representation of OIDs. Other toolkits use a simple
-     string-representation of OIDs with good results. In practice, we have
-     found the interface comfortable and quick to work with, and it is a
-     simple matter (for what it's worth) to create applications compatible
-     with both ISO SR and Z39.50. Finally, the use of the
-     <literal>/oident</literal> database is by no means mandatory.
-     You can easily create your own system for representing OIDs, as long
-     as it is compatible with the low-level integer-array representation
-     of the ODR module.
-    </para>
-   </note>
-
-   </sect2>
   </sect1>
   <sect1 id="tools.nmem"><title>Nibble Memory</title>
 
   </sect1>
   <sect1 id="tools.nmem"><title>Nibble Memory</title>
 
@@ -1986,9 +1792,9 @@ typedef struct oident
    <screen>
     NMEM nmem_create(void);
     void nmem_destroy(NMEM n);
    <screen>
     NMEM nmem_create(void);
     void nmem_destroy(NMEM n);
-    void *nmem_malloc(NMEM n, int size);
+    void *nmem_malloc(NMEM n, size_t size);
     void nmem_reset(NMEM n);
     void nmem_reset(NMEM n);
-    int nmem_total(NMEM n);
+    size_t nmem_total(NMEM n);
     void nmem_init(void);
     void nmem_exit(void);
    </screen>
     void nmem_init(void);
     void nmem_exit(void);
    </screen>
@@ -2016,16 +1822,16 @@ typedef struct oident
     <emphasis>not</emphasis> call <function>nmem_init</function> or
     <function>nmem_exit</function> unless you're absolute sure what
     you're doing. Note that in previous &yaz; versions you'd have to call
     <emphasis>not</emphasis> call <function>nmem_init</function> or
     <function>nmem_exit</function> unless you're absolute sure what
     you're doing. Note that in previous &yaz; versions you'd have to call
-    <function>nmem_init</function> yourself. 
+    <function>nmem_init</function> yourself.
    </para>
 
   </sect1>
 
   <sect1 id="tools.log"><title>Log</title>
   <para>
    </para>
 
   </sect1>
 
   <sect1 id="tools.log"><title>Log</title>
   <para>
-   &yaz; has evolved a fairly complex log system which should be useful both 
+   &yaz; has evolved a fairly complex log system which should be useful both
    for debugging &yaz; itself, debugging applications that use &yaz;, and for
    for debugging &yaz; itself, debugging applications that use &yaz;, and for
-   production use of those applications.  
+   production use of those applications.
   </para>
   <para>
    The log functions are declared in header <filename>yaz/log.h</filename>
   </para>
   <para>
    The log functions are declared in header <filename>yaz/log.h</filename>
@@ -2079,7 +1885,7 @@ typedef struct oident
    logged. This string should be a comma-separated list of log level names,
    and can contain both hard-coded names and dynamic ones. The log level
    calculation starts with <literal>YLOG_DEFAULT_LEVEL</literal> and adds a bit
    logged. This string should be a comma-separated list of log level names,
    and can contain both hard-coded names and dynamic ones. The log level
    calculation starts with <literal>YLOG_DEFAULT_LEVEL</literal> and adds a bit
-   for each word it meets, unless the word starts with a '-', in which case it 
+   for each word it meets, unless the word starts with a '-', in which case it
    clears the bit. If the string <literal>'none'</literal> is found,
    all bits are cleared. Typically this string comes from the command-line,
    often identified by <literal>-v</literal>. The
    clears the bit. If the string <literal>'none'</literal> is found,
    all bits are cleared. Typically this string comes from the command-line,
    often identified by <literal>-v</literal>. The
@@ -2088,15 +1894,15 @@ typedef struct oident
   </para>
 
   <para>
   </para>
 
   <para>
-   Each module should check what log bits it should be used, by calling 
+   Each module should check what log bits it should be used, by calling
    <function>yaz_log_module_level</function> with a suitable name for the
    module. The name is cleared from a preceding path and an extension, if any,
    so it is quite possible to use <literal>__FILE__</literal> for it. If the
    name has been passed to <function>yaz_log_mask_str</function>, the routine
    returns a non-zero bitmask, which should then be used in consequent calls
    to yaz_log. (It can also be tested, so as to avoid unnecessary calls to
    <function>yaz_log_module_level</function> with a suitable name for the
    module. The name is cleared from a preceding path and an extension, if any,
    so it is quite possible to use <literal>__FILE__</literal> for it. If the
    name has been passed to <function>yaz_log_mask_str</function>, the routine
    returns a non-zero bitmask, which should then be used in consequent calls
    to yaz_log. (It can also be tested, so as to avoid unnecessary calls to
-   yaz_log, in time-critical places, or when the log entry would take time 
-   to construct.) 
+   yaz_log, in time-critical places, or when the log entry would take time
+   to construct.)
   </para>
 
   <para>
   </para>
 
   <para>
@@ -2158,24 +1964,24 @@ typedef struct oident
   <para>
    The log system is almost independent of the rest of &yaz;, the only
    important dependence is of <filename>nmem</filename>, and that only for
   <para>
    The log system is almost independent of the rest of &yaz;, the only
    important dependence is of <filename>nmem</filename>, and that only for
-   using the semaphore definition there. 
+   using the semaphore definition there.
   </para>
 
   <para>
    The dynamic log levels and log rotation were introduced in &yaz; 2.0.28. At
    the same time, the log bit names were changed from
   </para>
 
   <para>
    The dynamic log levels and log rotation were introduced in &yaz; 2.0.28. At
    the same time, the log bit names were changed from
-   <literal>LOG_something</literal> to <literal>YLOG_something</literal>, 
+   <literal>LOG_something</literal> to <literal>YLOG_something</literal>,
    to avoid collision with <filename>syslog.h</filename>.
   </para>
 
   </sect1>
    to avoid collision with <filename>syslog.h</filename>.
   </para>
 
   </sect1>
-  
+
   <sect1 id="marc"><title>MARC</title>
   <sect1 id="marc"><title>MARC</title>
-   
+
    <para>
    <para>
-    YAZ provides a fast utility that decodes MARC records and
-    encodes to a varity of output formats. The MARC records must
-    be encoded in ISO2709.
+    YAZ provides a fast utility for working with MARC records.
+    Early versions of the MARC utility only allowed decoding of ISO2709.
+    Today the utility may both encode - and decode to a varity of formats.
    </para>
    <synopsis><![CDATA[
     #include <yaz/marcdisp.h>
    </para>
    <synopsis><![CDATA[
     #include <yaz/marcdisp.h>
@@ -2193,6 +1999,8 @@ typedef struct oident
     #define YAZ_MARC_MARCXML   3
     #define YAZ_MARC_ISO2709   4
     #define YAZ_MARC_XCHANGE   5
     #define YAZ_MARC_MARCXML   3
     #define YAZ_MARC_ISO2709   4
     #define YAZ_MARC_XCHANGE   5
+    #define YAZ_MARC_CHECK     6
+    #define YAZ_MARC_TURBOMARC 7
 
     /* supply iconv handle for character set conversion .. */
     void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd);
 
     /* supply iconv handle for character set conversion .. */
     void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd);
@@ -2202,15 +2010,22 @@ typedef struct oident
 
     /* decode MARC in buf of size bsize. Returns >0 on success; <=0 on failure.
     On success, result in *result with size *rsize. */
 
     /* decode MARC in buf of size bsize. Returns >0 on success; <=0 on failure.
     On success, result in *result with size *rsize. */
-    int yaz_marc_decode_buf (yaz_marc_t mt, const char *buf, int bsize,
-                             char **result, int *rsize);
+    int yaz_marc_decode_buf(yaz_marc_t mt, const char *buf, int bsize,
+                            const char **result, size_t *rsize);
 
     /* decode MARC in buf of size bsize. Returns >0 on success; <=0 on failure.
        On success, result in WRBUF */
 
     /* decode MARC in buf of size bsize. Returns >0 on success; <=0 on failure.
        On success, result in WRBUF */
-    int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf,
-                               int bsize, WRBUF wrbuf);
+    int yaz_marc_decode_wrbuf(yaz_marc_t mt, const char *buf,
+                              int bsize, WRBUF wrbuf);
 ]]>
    </synopsis>
 ]]>
    </synopsis>
+   <note>
+    <para>
+     The synopsis is just a basic subset of all functionality. Refer
+     to the actual header file <filename>marcdisp.h</filename> for
+     details.
+    </para>
+   </note>
    <para>
     A MARC conversion handle must be created by using
     <function>yaz_marc_create</function> and destroyed
    <para>
     A MARC conversion handle must be created by using
     <function>yaz_marc_create</function> and destroyed
@@ -2235,7 +2050,7 @@ typedef struct oident
       <term>YAZ_MARC_MARCXML</term>
       <listitem>
        <para>
       <term>YAZ_MARC_MARCXML</term>
       <listitem>
        <para>
-       The resulting record is converted to MARCXML.
+       <ulink url="&url.marcxml;">MARCXML</ulink>.
        </para>
       </listitem>
      </varlistentry>
        </para>
       </listitem>
      </varlistentry>
@@ -2244,14 +2059,45 @@ typedef struct oident
       <term>YAZ_MARC_ISO2709</term>
       <listitem>
        <para>
       <term>YAZ_MARC_ISO2709</term>
       <listitem>
        <para>
-       The resulting record is converted to ISO2709 (MARC).
+       ISO2709 (sometimes just referred to as "MARC").
        </para>
       </listitem>
      </varlistentry>
        </para>
       </listitem>
      </varlistentry>
+
+     <varlistentry>
+      <term>YAZ_MARC_XCHANGE</term>
+      <listitem>
+       <para>
+       <ulink url="&url.marcxchange;">MarcXchange</ulink>.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term>YAZ_MARC_CHECK</term>
+      <listitem>
+       <para>
+       Pseudo format for validation only. Does not generate
+       any real output except diagnostics.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term>YAZ_MARC_TURBOMARC</term>
+      <listitem>
+       <para>
+       XML format with same semantics as MARCXML but more compact
+       and geared towards fast processing with XSLT. Refer to
+       <xref linkend="tools.turbomarc"/> for more information.
+       </para>
+      </listitem>
+     </varlistentry>
+
     </variablelist>
    </para>
    <para>
     </variablelist>
    </para>
    <para>
-    The actual conversion functions are 
+    The actual conversion functions are
     <function>yaz_marc_decode_buf</function> and
     <function>yaz_marc_decode_wrbuf</function> which decodes and encodes
     a MARC record. The former function operates on simple buffers, the
     <function>yaz_marc_decode_buf</function> and
     <function>yaz_marc_decode_wrbuf</function> which decodes and encodes
     a MARC record. The former function operates on simple buffers, the
@@ -2261,13 +2107,13 @@ typedef struct oident
    <example id="example.marc.display">
     <title>Display of MARC record</title>
     <para>
    <example id="example.marc.display">
     <title>Display of MARC record</title>
     <para>
-     The followint program snippet illustrates how the MARC API may
+     The following program snippet illustrates how the MARC API may
      be used to convert a MARC record to the line-by-line format:
      <programlisting><![CDATA[
       void print_marc(const char *marc_buf, int marc_buf_size)
       {
          char *result;      /* for result buf */
      be used to convert a MARC record to the line-by-line format:
      <programlisting><![CDATA[
       void print_marc(const char *marc_buf, int marc_buf_size)
       {
          char *result;      /* for result buf */
-         int result_len;    /* for size of result */
+         size_t result_len;    /* for size of result */
          yaz_marc_t mt = yaz_marc_create();
          yaz_marc_xml(mt, YAZ_MARC_LINE);
          yaz_marc_decode_buf(mt, marc_buf, marc_buf_size,
          yaz_marc_t mt = yaz_marc_create();
          yaz_marc_xml(mt, YAZ_MARC_LINE);
          yaz_marc_decode_buf(mt, marc_buf, marc_buf_size,
@@ -2279,6 +2125,71 @@ typedef struct oident
       </programlisting>
     </para>
    </example>
       </programlisting>
     </para>
    </example>
+   <sect2 id="tools.turbomarc">
+    <title>TurboMARC</title>
+    <para>
+     TurboMARC is yet another XML encoding of a MARC record. The format
+     was designed for fast processing with XSLT.
+    </para>
+    <para>
+     Applications like
+     Pazpar2 uses XSLT to convert an XML encoded MARC record to an internal
+     representation. This conversion mostly check the tag of a MARC field
+     to determine the basic rules in the conversion. This check is
+     costly when that is tag is encoded as an attribute in MARCXML.
+     By having the tag value as the element instead, makes processing
+     many times faster (at least for Libxslt).
+    </para>
+    <para>
+     TurboMARC is encoded as follows:
+     <itemizedlist>
+      <listitem><para>
+       Record elements is part of namespace
+       "<literal>http://www.indexdata.com/turbomarc</literal>".
+       </para></listitem>
+      <listitem><para>
+       A record is enclosed in element <literal>r</literal>.
+       </para></listitem>
+      <listitem><para>
+       A collection of records is enclosed in element
+       <literal>collection</literal>.
+       </para></listitem>
+      <listitem><para>
+       The leader is encoded as element <literal>l</literal> with the
+       leader content as its (text) value.
+       </para></listitem>
+      <listitem><para>
+       A control field is encoded as element <literal>c</literal> concatenated
+       with the tag value of the control field if the tag value
+       matches the regular expression <literal>[a-zA-Z0-9]*</literal>.
+       If the tag value do not match the regular expression
+       <literal>[a-zA-Z0-9]*</literal> the control field is encoded
+       as element <literal>c</literal> and attribute <literal>code</literal>
+       will hold the tag value.
+       This rule ensure that in the rare cases where a tag value might
+       result in a non-wellformed XML YAZ encode it as a coded attribute
+       (as in MARCXML).
+       </para>
+       <para>
+       The control field content is the the text value of this element.
+       Indicators are encoded as attribute names
+       <literal>i1</literal>, <literal>i2</literal>, etc.. and
+       corresponding values for each indicator.
+       </para></listitem>
+      <listitem><para>
+       A data field is encoded as element <literal>d</literal> concatenated
+       with the tag value of the data field or using the attribute
+       <literal>code</literal> as described in the rules for control fields.
+       The children of the data field element is subfield elements.
+       Each subfield element is encoded as <literal>s</literal>
+       concatenated with the sub field code.
+       The text of the subfield element is the contents of the subfield.
+       Indicators are encoded as attributes for the data field element similar
+       to the encoding for control fields.
+       </para></listitem>
+     </itemizedlist>
+    </para>
+   </sect2>
   </sect1>
 
   <sect1 id="tools.retrieval">
   </sect1>
 
   <sect1 id="tools.retrieval">
@@ -2287,7 +2198,7 @@ typedef struct oident
     YAZ version 2.1.20 or later includes a Retrieval facility tool
     which allows a SRU/Z39.50 to describe itself and perform record
     conversions. The idea is the following:
     YAZ version 2.1.20 or later includes a Retrieval facility tool
     which allows a SRU/Z39.50 to describe itself and perform record
     conversions. The idea is the following:
-    
+
     <itemizedlist>
      <listitem>
       <para>
     <itemizedlist>
      <listitem>
       <para>
@@ -2335,13 +2246,13 @@ typedef struct oident
    <sect2 id="tools.retrieval.format">
     <title>Retrieval XML format</title>
     <para>
    <sect2 id="tools.retrieval.format">
     <title>Retrieval XML format</title>
     <para>
-     All elements should be covered by namespace 
+     All elements should be covered by namespace
      <literal>http://indexdata.com/yaz</literal> .
      The root element node must be <literal>retrievalinfo</literal>.
     </para>
     <para>
      The <literal>retrievalinfo</literal> must include one or
      <literal>http://indexdata.com/yaz</literal> .
      The root element node must be <literal>retrievalinfo</literal>.
     </para>
     <para>
      The <literal>retrievalinfo</literal> must include one or
-     more <literal>retrieval</literal> elements. Each 
+     more <literal>retrieval</literal> elements. Each
     <literal>retrieval</literal> defines specific combination of
      syntax, name and identifier supported by this retrieval service.
     </para>
     <literal>retrieval</literal> defines specific combination of
      syntax, name and identifier supported by this retrieval service.
     </para>
@@ -2363,7 +2274,10 @@ typedef struct oident
         <para>
          Defines the name of the retrieval format. This can be
          any string. For SRU, the value, is equivalent to schema (short-hand);
         <para>
          Defines the name of the retrieval format. This can be
          any string. For SRU, the value, is equivalent to schema (short-hand);
-         for Z39.50 it's equivalent to simple element set name. 
+         for Z39.50 it's equivalent to simple element set name.
+         For YAZ 3.0.24 and later this name may be specified as a glob
+         expression with operators
+         <literal>*</literal> and <literal>?</literal>.
         </para>
        </listitem>
       </varlistentry>
         </para>
        </listitem>
       </varlistentry>
@@ -2379,7 +2293,7 @@ typedef struct oident
      </variablelist>
     </para>
     <para>
      </variablelist>
     </para>
     <para>
-     The <literal>retrieval</literal> may include one 
+     The <literal>retrieval</literal> may include one
      <literal>backend</literal> element. If a <literal>backend</literal>
      element is given, it specifies how the records are retrieved by
      some backend and how the records are converted from the backend to
      <literal>backend</literal> element. If a <literal>backend</literal>
      element is given, it specifies how the records are retrieved by
      some backend and how the records are converted from the backend to
@@ -2400,16 +2314,16 @@ typedef struct oident
       <varlistentry><term><literal>marc</literal></term>
        <listitem>
         <para>
       <varlistentry><term><literal>marc</literal></term>
        <listitem>
         <para>
-         The <literal>marc</literal> element specifies a conversion 
-         to - and from ISO2709 encoded MARC and 
-         <ulink url="&url.marcxml;">&marcxml;</ulink>/MarcXchange.
+         The <literal>marc</literal> element specifies a conversion
+         to - and from ISO2709 encoded MARC and
+         <ulink url="&url.marcxml;">&acro.marcxml;</ulink>/MarcXchange.
          The following attributes may be specified:
 
          <variablelist>
           <varlistentry><term><literal>inputformat</literal> (REQUIRED)</term>
            <listitem>
             <para>
          The following attributes may be specified:
 
          <variablelist>
           <varlistentry><term><literal>inputformat</literal> (REQUIRED)</term>
            <listitem>
             <para>
-             Format of input. Supported values are 
+             Format of input. Supported values are
             <literal>marc</literal> (for ISO2709); and <literal>xml</literal>
              for MARCXML/MarcXchange.
             </para>
             <literal>marc</literal> (for ISO2709); and <literal>xml</literal>
              for MARCXML/MarcXchange.
             </para>
@@ -2419,8 +2333,8 @@ typedef struct oident
           <varlistentry><term><literal>outputformat</literal> (REQUIRED)</term>
            <listitem>
             <para>
           <varlistentry><term><literal>outputformat</literal> (REQUIRED)</term>
            <listitem>
             <para>
-             Format of output. Supported values are 
-            <literal>line</literal> (MARC line format); 
+             Format of output. Supported values are
+            <literal>line</literal> (MARC line format);
             <literal>marcxml</literal> (for MARCXML),
             <literal>marc</literal> (ISO2709),
             <literal>marcxhcange</literal> (for MarcXchange).
             <literal>marcxml</literal> (for MARCXML),
             <literal>marc</literal> (ISO2709),
             <literal>marcxhcange</literal> (for MarcXchange).
@@ -2456,7 +2370,7 @@ typedef struct oident
        <listitem>
         <para>
          The <literal>xslt</literal> element specifies a conversion
        <listitem>
         <para>
          The <literal>xslt</literal> element specifies a conversion
-         via &xslt;. The following attributes may be specified:
+         via &acro.xslt;. The following attributes may be specified:
 
          <variablelist>
           <varlistentry><term><literal>stylesheet</literal> (REQUIRED)</term>
 
          <variablelist>
           <varlistentry><term><literal>stylesheet</literal> (REQUIRED)</term>
@@ -2537,13 +2451,13 @@ typedef struct oident
     <para>
      It should be easy to use the retrieval systems from applications. Refer
      to the headers
     <para>
      It should be easy to use the retrieval systems from applications. Refer
      to the headers
-     <filename>yaz/retrieval.h</filename> and 
+     <filename>yaz/retrieval.h</filename> and
      <filename>yaz/record_conv.h</filename>.
     </para>
    </sect2>
   </sect1>
  </chapter>
      <filename>yaz/record_conv.h</filename>.
     </para>
    </sect2>
   </sect1>
  </chapter>
+
  <!-- Keep this comment at the end of the file
  Local variables:
  mode: sgml
  <!-- Keep this comment at the end of the file
  Local variables:
  mode: sgml