Mention that @mask requires YAZ 4.2.58
[yaz-moved-to-github.git] / doc / odr.xml
index db28c6c..770ad9c 100644 (file)
@@ -1,7 +1,6 @@
-<!-- $Id: odr.xml,v 1.3 2001-07-20 21:34:36 adam Exp $ -->
- <chapter><title id="odr">The ODR Module</title>
-  
-  <sect1><title>Introduction</title>
+ <chapter id="odr"><title>The ODR Module</title>
+
+  <sect1 id="odr.introduction"><title>Introduction</title>
 
    <para>
      &odr; is the BER-encoding/decoding subsystem of &yaz;. Care as been taken
 
    <para>
      &odr; is the BER-encoding/decoding subsystem of &yaz;. Care as been taken
    <para>
     If you are only interested in writing a Z39.50 implementation based on
     the PDUs that are already provided with &yaz;, you only need to concern
    <para>
     If you are only interested in writing a Z39.50 implementation based on
     the PDUs that are already provided with &yaz;, you only need to concern
-    yourself with the section on managing ODR streams (section
-    <link linkend="odr-use">Using ODR</link>). Only if you need to
+    yourself with the section on managing ODR streams
+    (<xref linkend="odr.use"/>). Only if you need to
     implement ASN.1 beyond that which has been provided, should you
     worry about the second half of the documentation
     implement ASN.1 beyond that which has been provided, should you
     worry about the second half of the documentation
-    (section <link linkend="odr-prog">Programming with ODR</link>).
+    (<xref linkend="odr.programming"/>).
     If you use one of the higher-level interfaces, you can skip this
     section entirely.
    </para>
 
    <para>
     If you use one of the higher-level interfaces, you can skip this
     section entirely.
    </para>
 
    <para>
-    This is important, so we'll repeat it for emphasis: <emphasis>You do not
-     need to read section <link linkend="odr-prog">Programming with ODR</link> to
-     implement Z39.50 with &yaz;.</emphasis>
+    This is important, so we'll repeat it for emphasis: <emphasis>You do
+     not need to read <xref linkend="odr.programming"/>
+     to implement Z39.50 with &yaz;.</emphasis>
    </para>
 
    <para>
    </para>
 
    <para>
@@ -37,9 +36,9 @@
    </para>
 
   </sect1>
    </para>
 
   </sect1>
-  <sect1><title id="odr-use">Using ODR</title>
+  <sect1 id="odr.use"><title>Using ODR</title>
 
 
-   <sect2><title>ODR Streams</title>
+   <sect2 id="odr.streams"><title>ODR Streams</title>
 
     <para>
      Conceptually, the ODR stream is the source of encoded data in the
 
     <para>
      Conceptually, the ODR stream is the source of encoded data in the
@@ -74,7 +73,7 @@
     </para>
    </sect2>
 
     </para>
    </sect2>
 
-   <sect2><title id="memory">Memory Management</title>
+   <sect2 id="odr.memory.management"><title id="memory">Memory Management</title>
 
     <para>
      Two forms of memory management take place in the &odr; system. The first
 
     <para>
      Two forms of memory management take place in the &odr; system. The first
@@ -95,7 +94,7 @@
     </para>
 
     <synopsis>
     </para>
 
     <synopsis>
-     void *odr_malloc(ODR o, int size);
+     void *odr_malloc(ODR o, size_t size);
     </synopsis>
 
     <para>
     </synopsis>
 
     <para>
     </para>
 
     <synopsis>
     </para>
 
     <synopsis>
-     void odr_reset(ODR o, int size);
+     void odr_reset(ODR o);
     </synopsis>
 
     <para>
     </synopsis>
 
     <para>
     </para>
 
     <synopsis>
     </para>
 
     <synopsis>
-     int odr_total(ODR o);
+     size_t odr_total(ODR o);
     </synopsis>
 
     <para>
     </synopsis>
 
     <para>
     <para>
      The memory subsystem of &odr; is fairly efficient at allocating and
      releasing little bits of memory. Rather than managing the individual,
     <para>
      The memory subsystem of &odr; is fairly efficient at allocating and
      releasing little bits of memory. Rather than managing the individual,
-     small bits of space, the system maintains a freelist of larger chunks
+     small bits of space, the system maintains a free-list of larger chunks
      of memory, which are handed out in small bits. This scheme is
      generally known as a <emphasis>nibble memory</emphasis> system.
      of memory, which are handed out in small bits. This scheme is
      generally known as a <emphasis>nibble memory</emphasis> system.
-     It is very useful for maintaing short-lived constructions such
+     It is very useful for maintaining short-lived constructions such
      as protocol PDUs.
     </para>
 
      as protocol PDUs.
     </para>
 
     </para>
 
    </sect2>
     </para>
 
    </sect2>
-   <sect2><title>Encoding and Decoding Data</title>
+   <sect2 id="odr.encoding.and.decoding"><title>Encoding and Decoding Data</title>
 
     <para>
      When encoding data, the ODR stream will write the encoded octet string
 
     <para>
      When encoding data, the ODR stream will write the encoded octet string
      The integer pointed to by len is set to the length of the encoded
      data, and a pointer to that data is returned. <literal>*size</literal>
      is set to the size of the buffer (unless <literal>size</literal> is null,
      The integer pointed to by len is set to the length of the encoded
      data, and a pointer to that data is returned. <literal>*size</literal>
      is set to the size of the buffer (unless <literal>size</literal> is null,
-     signalling that you are not interested in the size). The next call to
+     signaling that you are not interested in the size). The next call to
      a primitive function using the same &odr; stream will overwrite the
      data, unless a different buffer has been supplied using the call
     </para>
      a primitive function using the same &odr; stream will overwrite the
      data, unless a different buffer has been supplied using the call
     </para>
     </para>
 
     <para>
     </para>
 
     <para>
-     It is important to realise that the ODR stream will not release this
+     It is important to realize that the ODR stream will not release this
      memory when you call <function>odr_reset()</function>: It will
      merely update its internal pointers to prepare for the encoding of a
      new data value.
      memory when you call <function>odr_reset()</function>: It will
      merely update its internal pointers to prepare for the encoding of a
      new data value.
      be released <emphasis>only</emphasis> if the <literal>can_grow</literal>
      parameter to <function>odr_setbuf()</function> was nonzero. The
      <literal>can_grow</literal> parameter, in other words, is a way of
      be released <emphasis>only</emphasis> if the <literal>can_grow</literal>
      parameter to <function>odr_setbuf()</function> was nonzero. The
      <literal>can_grow</literal> parameter, in other words, is a way of
-     signalling who is to own the buffer, you or the ODR stream. If you never call
+     signaling who is to own the buffer, you or the ODR stream. If you never call
      <function>odr_setbuf()</function> on your encoding stream, which is
      typically the case, the buffer allocated by the stream will belong to
      the stream by default.
      <function>odr_setbuf()</function> on your encoding stream, which is
      typically the case, the buffer allocated by the stream will belong to
      the stream by default.
      <function>z_APDU()</function>).
     </para>
 
      <function>z_APDU()</function>).
     </para>
 
-    <para>
-     Examples of encoding/decoding functions:
-    </para>
-
-    <synopsis>
-     int odr_integer(ODR o, int **p, int optional, const char *name);
+    <example id="example.odr.encoding.and.decoding.functions">
+     <title>Encoding and decoding functions</title>
+     <synopsis>
+      int odr_integer(ODR o, Odr_int **p, int optional, const char *name);
 
 
-     int z_APDU(ODR o, Z_APDU **p, int optional, const char *name);
-    </synopsis>
+      int z_APDU(ODR o, Z_APDU **p, int optional, const char *name);
+     </synopsis>
+    </example>
 
     <para>
      If the data is absent (or doesn't match the tag corresponding to
 
     <para>
      If the data is absent (or doesn't match the tag corresponding to
      <function>free(2)</function> to release the memory.
      You can decode several data elements (by repeated calls to
      <function>odr_setbuf()</function> and your decoding function), and
      <function>free(2)</function> to release the memory.
      You can decode several data elements (by repeated calls to
      <function>odr_setbuf()</function> and your decoding function), and
-     new memory will be allocated each time. When you do call 
+     new memory will be allocated each time. When you do call
      <function>odr_reset()</function>, everything decoded since the
      last call to <function>odr_reset()</function> will be released.
     </para>
 
      <function>odr_reset()</function>, everything decoded since the
      last call to <function>odr_reset()</function> will be released.
     </para>
 
-    <para>
-     The use of the double indirection can be a little confusing at first
-     (its purpose will become clear later on, hopefully),
-     so an example is in order. We'll encode an integer value, and
-     immediately decode it again using a different stream. A useless, but
-     informative operation.
-    </para>
-
-    <programlisting>
-
-void do_nothing_useful(int value)
+    <example id="example.odr.encoding.of.integer">
+     <title>Encoding and decoding of an integer</title>
+     <para>
+      The use of the double indirection can be a little confusing at first
+      (its purpose will become clear later on, hopefully),
+      so an example is in order. We'll encode an integer value, and
+      immediately decode it again using a different stream. A useless, but
+      informative operation.
+     </para>
+     <programlisting><![CDATA[
+void do_nothing_useful(Odr_int value)
 {
     ODR encode, decode;
 {
     ODR encode, decode;
-    int *valp, *resvalp;
+    Odr_int *valp, *resvalp;
     char *bufferp;
     int len;
     char *bufferp;
     int len;
-     
+
     /* allocate streams */
     if (!(encode = odr_createmem(ODR_ENCODE)))
         return;
     if (!(decode = odr_createmem(ODR_DECODE)))
         return;
 
     /* allocate streams */
     if (!(encode = odr_createmem(ODR_ENCODE)))
         return;
     if (!(decode = odr_createmem(ODR_DECODE)))
         return;
 
-    valp = &amp;value;
-    if (odr_integer(encode, &amp;valp, 0, 0) == 0)
+    valp = &value;
+    if (odr_integer(encode, &valp, 0, 0) == 0)
     {
         printf("encoding went bad\n");
         return;
     }
     {
         printf("encoding went bad\n");
         return;
     }
-    bufferp = odr_getbuf(encode, &amp;len);
-    printf("length of encoded data is &percnt;d\n", len);
+    bufferp = odr_getbuf(encode, &len, 0);
+    printf("length of encoded data is %d\n", len);
 
     /* now let's decode the thing again */
 
     /* now let's decode the thing again */
-    odr_setbuf(decode, bufferp, len);
-    if (odr_integer(decode, &amp;resvalp, 0, 0) == 0)
+    odr_setbuf(decode, bufferp, len, 0);
+    if (odr_integer(decode, &resvalp, 0, 0) == 0)
     {
         printf("decoding went bad\n");
         return;
     }
     {
         printf("decoding went bad\n");
         return;
     }
-    printf("the value is &percnt;d\n", *resvalp);
+    /* ODR_INT_PRINTF format for printf (such as %d) */
+    printf("the value is " ODR_INT_PRINTF "\n", *resvalp);
 
     /* clean up */
     odr_destroy(encode);
     odr_destroy(decode);
 }
 
     /* clean up */
     odr_destroy(encode);
     odr_destroy(decode);
 }
-    </programlisting>
+]]>
+     </programlisting>
+     <para>
+      This looks like a lot of work, offhand. In practice, the &odr; streams
+      will typically be allocated once, in the beginning of your program
+      (or at the beginning of a new network session), and the encoding
+      and decoding will only take place in a few, isolated places in your
+      program, so the overhead is quite manageable.
+     </para>
+    </example>
+
+   </sect2>
 
 
+   <sect2 id="odr.printing"><title>Printing</title>
     <para>
     <para>
-     This looks like a lot of work, offhand. In practice, the &odr; streams
-     will typically be allocated once, in the beginning of your program
-     (or at the beginning of a new network session), and the encoding
-     and decoding will only take place in a few, isolated places in your
-     program, so the overhead is quite manageable.
+     When an ODR stream is created of type <literal>ODR_PRINT</literal>
+     the ODR module will print the contents of a PDU in a readable format.
+     By default output is written to the <literal>stderr</literal> stream.
+     This behavior can be changed, however, by calling the function
+     <synopsis>
+      odr_setprint(ODR o, FILE *file);
+     </synopsis>
+     before encoders or decoders are being invoked.
+     It is also possible to direct the output to a buffer (of indeed
+     another file), by using the more generic mechanism:
+     <synopsis>
+      void odr_set_stream(ODR o, void *handle,
+                         void (*stream_write)(ODR o, void *handle, int type,
+                                              const char *buf, int len),
+                         void (*stream_close)(void *handle));
+     </synopsis>
+     Here the user provides an opaque handle and two handlers,
+     <replaceable>stream_write</replaceable> for writing,
+     and <replaceable>stream_close</replaceable> which is supposed
+     to close/free resources associated with handle.
+     The <replaceable>stream_close</replaceable> handler is optional and
+     if NULL for the function is provided, it will not be invoked.
+     The <replaceable>stream_write</replaceable> takes the ODR handle
+     as parameter, the user defined handle, a type
+     <literal>ODR_OCTETSTRING</literal>, <literal>ODR_VISIBLESTRING</literal>
+     which indicates the type of contents is being written.
     </para>
     </para>
-
+    <para>
+     Another utility useful for diagnostics (error handling) or as
+     part of the printing facilities is:
+     <synopsis>
+      const char **odr_get_element_path(ODR o);
+     </synopsis>
+     which returns a list of current elements that ODR deals with at the
+     moment. For the returned array, say <literal>ar</literal>,
+     <literal>ar[0]</literal> is the top level element,
+     <literal>ar[n]</literal> is the last. The last element has the
+     property that <literal>ar[n+1] == NULL</literal>.
+    </para>
+    <example id="example.odr.element.path.record">
+     <title>Element Path for record</title>
+     <para>
+      For a database record part of a PresentResponse the
+      array returned by <function>odr_get_element</function>
+      is <literal>presentResponse</literal>, <literal>databaseOrSurDiagnostics</literal>, <literal>?</literal>, <literal>record</literal>, <literal>?</literal>, <literal>databaseRecord</literal> . The question mark appears due to
+      unnamed constructions.
+     </para>
+     </example>
    </sect2>
    </sect2>
-
-   <sect2><title>Diagnostics</title>
+   <sect2 id="odr.diagnostics"><title>Diagnostics</title>
 
     <para>
      The encoding/decoding functions all return 0 when an error occurs.
 
     <para>
      The encoding/decoding functions all return 0 when an error occurs.
@@ -391,7 +442,8 @@ void do_nothing_useful(int value)
      one of these constants:
     </para>
 
      one of these constants:
     </para>
 
-    <table frame="top"><title>ODR Error codes</title>
+    <table frame="top" id="odr.error.codes">
+     <title>ODR Error codes</title>
      <tgroup cols="2">
       <thead>
        <row>
      <tgroup cols="2">
       <thead>
        <row>
@@ -440,7 +492,7 @@ void do_nothing_useful(int value)
     </para>
 
     <synopsis>
     </para>
 
     <synopsis>
-     char *odr_errlist&lsqb;&rsqb;
+     char *odr_errlist[]
     </synopsis>
 
     <para>
     </synopsis>
 
     <para>
@@ -449,10 +501,11 @@ void do_nothing_useful(int value)
     </para>
 
    </sect2>
     </para>
 
    </sect2>
-   <sect2><title>Summary and Synopsis</title>
+   <sect2 id="odr.summary.and.synopsis">
+    <title>Summary and Synopsis</title>
 
     <synopsis>
 
     <synopsis>
-     #include &lt;odr.h>
+     #include &lt;yaz/odr.h>
 
      ODR odr_createmem(int direction);
 
 
      ODR odr_createmem(int direction);
 
@@ -460,19 +513,17 @@ void do_nothing_useful(int value)
 
      void odr_reset(ODR o);
 
 
      void odr_reset(ODR o);
 
-     char *odr_getbuf(ODR o, int *len);
+     char *odr_getbuf(ODR o, int *len, int *size);
 
 
-     void odr_setbuf(ODR o, char *buf, int len);
+     void odr_setbuf(ODR o, char *buf, int len, int can_grow);
 
      void *odr_malloc(ODR o, int size);
 
 
      void *odr_malloc(ODR o, int size);
 
-     ODR_MEM odr_extract_mem(ODR o);
-
-     void odr_release_mem(ODR_MEM r);
+     NMEM odr_extract_mem(ODR o);
 
      int odr_geterror(ODR o);
 
 
      int odr_geterror(ODR o);
 
-     void odr_perror(char *message);
+     void odr_perror(ODR o, const char *message);
 
      extern char *odr_errlist[];
     </synopsis>
 
      extern char *odr_errlist[];
     </synopsis>
@@ -480,7 +531,7 @@ void do_nothing_useful(int value)
    </sect2>
   </sect1>
 
    </sect2>
   </sect1>
 
-  <sect1><title id="odr-prog">Programming with ODR</title>
+  <sect1 id="odr.programming"><title>Programming with ODR</title>
 
    <para>
     The API of &odr; is designed to reflect the structure of ASN.1, rather
 
    <para>
     The API of &odr; is designed to reflect the structure of ASN.1, rather
@@ -488,39 +539,46 @@ void do_nothing_useful(int value)
     other external forms.
    </para>
 
     other external forms.
    </para>
 
+   <tip>
+    <para>
+     There is an ASN.1 tutorial available at
+     <ulink url="&url.asn.1.tutorial;">this site</ulink>.
+     This site also has standards for ASN.1 (X.680) and BER (X.690)
+     <ulink url="&url.asn.1.standards;">online</ulink>.
+    </para>
+   </tip>
+
    <para>
    <para>
-    The interface is based loosely on that of the Sun Microsystems XDR routines.
+    The ODR interface is based loosely on that of the Sun Microsystems
+    XDR routines.
     Specifically, each function which corresponds to an ASN.1 primitive
     type has a dual function. Depending on the settings of the ODR
     stream which is supplied as a parameter, the function may be used
     either to encode or decode data. The functions that can be built
     Specifically, each function which corresponds to an ASN.1 primitive
     type has a dual function. Depending on the settings of the ODR
     stream which is supplied as a parameter, the function may be used
     either to encode or decode data. The functions that can be built
-    using these primitive functions, to represent more complex datatypes, share
-    this quality. The result is that you only have to enter the definition
-    for a type once - and you have the functionality of encoding, decoding
-    (and pretty-printing) all in one unit. The resulting C source code is
-    quite compact, and is a pretty straightforward representation of the
-    source ASN.1 specification. Although no ASN.1 compiler is supplied
-    with &odr; at this time, it shouldn't be too difficult to write one, or
-    perhaps even to adapt an existing compiler to output &odr; routines
-    (not surprisingly, writing encoders/decoders using &odr; turns out
-    to be boring work).
+    using these primitive functions, to represent more complex data types,
+    share this quality. The result is that you only have to enter the
+    definition for a type once - and you have the functionality of encoding,
+    decoding (and pretty-printing) all in one unit.
+    The resulting C source code is quite compact, and is a pretty
+    straightforward representation of the source ASN.1 specification.
    </para>
 
    <para>
     In many cases, the model of the XDR functions works quite well in this
     role.
     In others, it is less elegant. Most of the hassle comes from the optional
    </para>
 
    <para>
     In many cases, the model of the XDR functions works quite well in this
     role.
     In others, it is less elegant. Most of the hassle comes from the optional
-    SEQUENCE memebers which don't exist in XDR.
+    SEQUENCE members which don't exist in XDR.
    </para>
 
    </para>
 
-   <sect2><title>The Primitive ASN.1 Types</title>
+   <sect2 id="odr.primitive.asn1.types">
+    <title>The Primitive ASN.1 Types</title>
 
     <para>
      ASN.1 defines a number of primitive types (many of which correspond
      roughly to primitive types in structured programming languages, such as C).
     </para>
 
 
     <para>
      ASN.1 defines a number of primitive types (many of which correspond
      roughly to primitive types in structured programming languages, such as C).
     </para>
 
-    <sect3><title>INTEGER</title>
+    <sect3 id="odr.integer"><title>INTEGER</title>
 
      <para>
       The &odr; function for encoding or decoding (or printing) the ASN.1
 
      <para>
       The &odr; function for encoding or decoding (or printing) the ASN.1
@@ -528,11 +586,11 @@ void do_nothing_useful(int value)
      </para>
 
      <synopsis>
      </para>
 
      <synopsis>
-int odr_integer(ODR o, int **p, int optional, const char *name);
+      int odr_integer(ODR o, Odr_int **p, int optional, const char *name);
      </synopsis>
 
      <para>
      </synopsis>
 
      <para>
-      (we don't allow values that can't be contained in a C integer.)
+      The <literal>Odr_int</literal> is just a simple integer.
      </para>
 
      <para>
      </para>
 
      <para>
@@ -578,24 +636,24 @@ int odr_integer(ODR o, int **p, int optional, const char *name);
       similar manners:
      </para>
     </sect3>
       similar manners:
      </para>
     </sect3>
-    <sect3><title>BOOLEAN</title>
+    <sect3 id="odr.boolean"><title>BOOLEAN</title>
 
      <synopsis>
 
      <synopsis>
-int odr_bool(ODR o, bool_t **p, int optional, const char *name);
+int odr_bool(ODR o, Odr_bool **p, int optional, const char *name);
      </synopsis>
 
     </sect3>
      </synopsis>
 
     </sect3>
-    <sect3><title>REAL</title>
+    <sect3 id="odr.real"><title>REAL</title>
 
      <para>
       Not defined.
      </para>
 
     </sect3>
 
      <para>
       Not defined.
      </para>
 
     </sect3>
-    <sect3><title>NULL</title>
+    <sect3 id="odr.null"><title>NULL</title>
 
      <synopsis>
 
      <synopsis>
-int odr_null(ODR o, bool_t **p, int optional, const char *name);
+int odr_null(ODR o, Odr_null **p, int optional, const char *name);
      </synopsis>
 
      <para>
      </synopsis>
 
      <para>
@@ -605,7 +663,7 @@ int odr_null(ODR o, bool_t **p, int optional, const char *name);
      </para>
 
     </sect3>
      </para>
 
     </sect3>
-    <sect3><title>OCTET STRING</title>
+    <sect3 id="odr.octet.string"><title>OCTET STRING</title>
 
      <synopsis>
 typedef struct odr_oct
 
      <synopsis>
 typedef struct odr_oct
@@ -652,7 +710,7 @@ int odr_visiblestring(ODR o, char **p, int optional,
      </synopsis>
 
     </sect3>
      </synopsis>
 
     </sect3>
-    <sect3><title>BIT STRING</title>
+    <sect3 id="odr.bit.string"><title>BIT STRING</title>
 
      <synopsis>
 int odr_bitstring(ODR o, Odr_bitmask **p, int optional,
 
      <synopsis>
 int odr_bitstring(ODR o, Odr_bitmask **p, int optional,
@@ -682,7 +740,7 @@ int ODR_MASK_GET(Odr_bitmask *b, int bitno);
      </synopsis>
 
      <para>
      </synopsis>
 
      <para>
-      The functions are modelled after the manipulation functions that
+      The functions are modeled after the manipulation functions that
       accompany the <literal>fd_set</literal> type used by the
       <function>select(2)</function> call.
       <literal>ODR_MASK_ZERO</literal> should always be called first on a
       accompany the <literal>fd_set</literal> type used by the
       <function>select(2)</function> call.
       <literal>ODR_MASK_ZERO</literal> should always be called first on a
@@ -690,28 +748,28 @@ int ODR_MASK_GET(Odr_bitmask *b, int bitno);
      </para>
     </sect3>
 
      </para>
     </sect3>
 
-    <sect3><title>OBJECT IDENTIFIER</title>
+    <sect3 id="odr.object.identifier"><title>OBJECT IDENTIFIER</title>
 
      <synopsis>
 int odr_oid(ODR o, Odr_oid **p, int optional, const char *name);
      </synopsis>
 
      <para>
 
      <synopsis>
 int odr_oid(ODR o, Odr_oid **p, int optional, const char *name);
      </synopsis>
 
      <para>
-      The C OID represenation is simply an array of integers, terminated by
+      The C OID representation is simply an array of integers, terminated by
       the value -1 (the <literal>Odr_oid</literal> type is synonymous with
       the value -1 (the <literal>Odr_oid</literal> type is synonymous with
-      the <literal>int</literal> type).
-      We suggest that you use the OID database module (see section
-      <link linkend="oid">Object Identifiers</link>) to handle object identifiers
+      the <literal>short</literal> type).
+      We suggest that you use the OID database module (see
+      <xref linkend="tools.oid.database"/>) to handle object identifiers
       in your application.
      </para>
 
     </sect3>
    </sect2>
       in your application.
      </para>
 
     </sect3>
    </sect2>
-   <sect2><title id="tag-prim">Tagging Primitive Types</title>
+   <sect2 id="odr.tagging.primitive.types"><title>Tagging Primitive Types</title> <!-- tag.prim -->
 
     <para>
      The simplest way of tagging a type is to use the
 
     <para>
      The simplest way of tagging a type is to use the
-     <function>odr_implicit_tag()</function> or 
+     <function>odr_implicit_tag()</function> or
      <function>odr_explicit_tag()</function> macros:
     </para>
 
      <function>odr_explicit_tag()</function> macros:
     </para>
 
@@ -729,7 +787,7 @@ int odr_explicit_tag(ODR o, Odr_fun fun, int class, int tag,
     </para>
 
     <screen>
     </para>
 
     <screen>
-     MyInt ::= &lsqb;210&rsqb; IMPLICIT INTEGER
+     MyInt ::= [210] IMPLICIT INTEGER
     </screen>
 
     <para>
     </screen>
 
     <para>
@@ -737,7 +795,7 @@ int odr_explicit_tag(ODR o, Odr_fun fun, int class, int tag,
     </para>
 
     <screen>
     </para>
 
     <screen>
-int myInt(ODR o, int **p, int optional, const char *name)
+int myInt(ODR o, Odr_int **p, int optional, const char *name)
 {
     return odr_implicit_tag(o, odr_integer, p,
                            ODR_CONTEXT, 210, optional, name);
 {
     return odr_implicit_tag(o, odr_integer, p,
                            ODR_CONTEXT, 210, optional, name);
@@ -747,8 +805,8 @@ int myInt(ODR o, int **p, int optional, const char *name)
     <para>
      The function <function>myInt()</function> can then be used like any of
      the primitive functions provided by &odr;. Note that the behavior of
     <para>
      The function <function>myInt()</function> can then be used like any of
      the primitive functions provided by &odr;. Note that the behavior of
-     <function>odr_explicit()</function>
-     and <function>odr_implicit()</function> macros
+     <function>odr_explicit_tag()</function>
+     and <function>odr_implicit_tag()</function> macros
      act exactly the same as the functions they are applied to - they
      respond to error conditions, etc, in the same manner - they
      simply have three extra parameters. The class parameter may
      act exactly the same as the functions they are applied to - they
      respond to error conditions, etc, in the same manner - they
      simply have three extra parameters. The class parameter may
@@ -758,7 +816,7 @@ int myInt(ODR o, int **p, int optional, const char *name)
     </para>
 
    </sect2>
     </para>
 
    </sect2>
-   <sect2><title>Constructed Types</title>
+   <sect2 id="odr.constructed.types"><title>Constructed Types</title>
 
     <para>
      Constructed types are created by combining primitive types. The
 
     <para>
      Constructed types are created by combining primitive types. The
@@ -809,10 +867,10 @@ MySequence ::= SEQUENCE {
     <screen>
 typedef struct MySequence
 {
     <screen>
 typedef struct MySequence
 {
-    int *intval;
-    bool_t *boolval;
+    Odr_int *intval;
+    Odr_bool *boolval;
 } MySequence;
 } MySequence;
-     
+
 int mySequence(ODR o, MySequence **p, int optional, const char *name)
 {
     if (odr_sequence_begin(o, p, sizeof(**p), name) == 0)
 int mySequence(ODR o, MySequence **p, int optional, const char *name)
 {
     if (odr_sequence_begin(o, p, sizeof(**p), name) == 0)
@@ -829,7 +887,8 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name)
      Note the 1 in the call to <function>odr_bool()</function>, to mark
      that the sequence member is optional.
      If either of the member types had been tagged, the macros
      Note the 1 in the call to <function>odr_bool()</function>, to mark
      that the sequence member is optional.
      If either of the member types had been tagged, the macros
-     <function>odr_implicit()</function> or <function>odr_explicit()</function>
+     <function>odr_implicit_tag()</function> or
+     <function>odr_explicit_tag()</function>
      could have been used.
      The new function can be used exactly like the standard functions provided
      with &odr;. It will encode, decode or pretty-print a data value of the
      could have been used.
      The new function can be used exactly like the standard functions provided
      with &odr;. It will encode, decode or pretty-print a data value of the
@@ -839,29 +898,30 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name)
      You could, of course, name your structures, types, and functions any way
      you please - as long as you're consistent, and your code is easily readable.
      <literal>odr_ok</literal> is just that - a predicate that returns the
      You could, of course, name your structures, types, and functions any way
      you please - as long as you're consistent, and your code is easily readable.
      <literal>odr_ok</literal> is just that - a predicate that returns the
-     state of the stream. It is used to ensure that the behaviour of the new
+     state of the stream. It is used to ensure that the behavior of the new
      type is compatible with the interface of the primitive types.
     </para>
 
    </sect2>
      type is compatible with the interface of the primitive types.
     </para>
 
    </sect2>
-   <sect2><title>Tagging Constructed Types</title>
+   <sect2 id="odr.tagging.constructed.types">
+    <title>Tagging Constructed Types</title>
 
     <note>
      <para>
 
     <note>
      <para>
-      See section <link linkend="tag-prim">Tagging Primitive types</link>
-      for information on how to tag the primitive types, as well as types
-      that are already defined.
+      See <xref linkend="odr.tagging.primitive.types"/> for information on how to tag
+      the primitive types, as well as types that are already defined.
      </para>
     </note>
 
      </para>
     </note>
 
-    <sect3><title>Implicit Tagging</title>
+    <sect3 id="odr.implicit.tagging">
+     <title>Implicit Tagging</title>
 
      <para>
       Assume the type above had been defined as
      </para>
 
      <screen>
 
      <para>
       Assume the type above had been defined as
      </para>
 
      <screen>
-MySequence ::= &lsqb;10&rsqb; IMPLICIT SEQUENCE {
+MySequence ::= [10] IMPLICIT SEQUENCE {
       intval INTEGER,
       boolval BOOLEAN OPTIONAL
 }
       intval INTEGER,
       boolval BOOLEAN OPTIONAL
 }
@@ -877,7 +937,7 @@ int odr_implicit_settag(ODR o, int class, int tag);
 
      <para>
       which overrides the tag of the type immediately following it. The
 
      <para>
       which overrides the tag of the type immediately following it. The
-      macro <function>odr_implicit()</function> works by calling
+      macro <function>odr_implicit_tag()</function> works by calling
       <function>odr_implicit_settag()</function> immediately
       before calling the function pointer argument.
       Your type function could look like this:
       <function>odr_implicit_settag()</function> immediately
       before calling the function pointer argument.
       Your type function could look like this:
@@ -902,7 +962,7 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name)
      </para>
     </sect3>
 
      </para>
     </sect3>
 
-    <sect3><title>Explicit Tagging</title>
+    <sect3 id="odr.explicit.tagging"><title>Explicit Tagging</title>
 
      <para>
       Explicit tagging of constructed types is a little more complicated,
 
      <para>
       Explicit tagging of constructed types is a little more complicated,
@@ -914,7 +974,7 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name)
      </para>
 
      <screen>
      </para>
 
      <screen>
-MySequence ::= &lsqb;10&rsqb; IMPLICIT SEQUENCE {
+MySequence ::= [10] IMPLICIT SEQUENCE {
    intval INTEGER,
    boolval BOOLEAN OPTIONAL
 }
    intval INTEGER,
    boolval BOOLEAN OPTIONAL
 }
@@ -963,11 +1023,11 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name)
       Notice that the interface here gets kind of nasty. The reason is
       simple: Explicitly tagged, constructed types are fairly rare in
       the protocols that we care about, so the
       Notice that the interface here gets kind of nasty. The reason is
       simple: Explicitly tagged, constructed types are fairly rare in
       the protocols that we care about, so the
-      aesthetic annoyance (not to mention the dangers of a cluttered
+      esthetic annoyance (not to mention the dangers of a cluttered
       interface) is less than the time that would be required to develop a
       better interface. Nevertheless, it is far from satisfying, and it's a
       point that will be worked on in the future. One option for you would
       interface) is less than the time that would be required to develop a
       better interface. Nevertheless, it is far from satisfying, and it's a
       point that will be worked on in the future. One option for you would
-      be to simply apply the <function>odr_explicit()</function> macro to
+      be to simply apply the <function>odr_explicit_tag()</function> macro to
       the first function, and not
       have to worry about <function>odr_constructed_*</function> yourself.
       Incidentally, as you might have guessed, the
       the first function, and not
       have to worry about <function>odr_constructed_*</function> yourself.
       Incidentally, as you might have guessed, the
@@ -977,10 +1037,10 @@ int mySequence(ODR o, MySequence **p, int optional, const char *name)
 
     </sect3>
    </sect2>
 
     </sect3>
    </sect2>
-   <sect2><title>SEQUENCE OF</title>
+   <sect2 id="odr.sequence.of"><title>SEQUENCE OF</title>
 
     <para>
 
     <para>
-     To handle sequences (arrays) of a apecific type, the function
+     To handle sequences (arrays) of a specific type, the function
     </para>
 
     <synopsis>
     </para>
 
     <synopsis>
@@ -1011,7 +1071,7 @@ MyArray ::= SEQUENCE OF INTEGER
 typedef struct MyArray
 {
     int num_elements;
 typedef struct MyArray
 {
     int num_elements;
-    int **elements;
+    Odr_int **elements;
 } MyArray;
     </screen>
 
 } MyArray;
     </screen>
 
@@ -1033,7 +1093,7 @@ int myArray(ODR o, MyArray **p, int optional, const char *name)
     </screen>
 
    </sect2>
     </screen>
 
    </sect2>
-   <sect2><title>CHOICE Types</title>
+   <sect2 id="odr.choice.types"><title>CHOICE Types</title>
 
     <para>
      The choice type is used fairly often in some ASN.1 definitions, so
 
     <para>
      The choice type is used fairly often in some ASN.1 definitions, so
@@ -1045,7 +1105,7 @@ int myArray(ODR o, MyArray **p, int optional, const char *name)
     </para>
 
     <synopsis>
     </para>
 
     <synopsis>
-int odr_choice(ODR o, Odr_arm arm&lsqb;&rsqb;, void *p, void *whichp,
+int odr_choice(ODR o, Odr_arm arm[], void *p, void *whichp,
                const char *name);
     </synopsis>
 
                const char *name);
     </synopsis>
 
@@ -1090,7 +1150,7 @@ typedef struct odr_arm
 
      <varlistentry><term>which</term>
       <listitem><para>The value of the discriminator that corresponds to
 
      <varlistentry><term>which</term>
       <listitem><para>The value of the discriminator that corresponds to
-       this CHOICE element. Typically, it will be a &num;defined constant, or
+       this CHOICE element. Typically, it will be a #defined constant, or
        an enum member.</para></listitem>
      </varlistentry>
 
        an enum member.</para></listitem>
      </varlistentry>
 
@@ -1115,7 +1175,7 @@ typedef struct odr_arm
     <screen>
 MyChoice ::= CHOICE {
     untagged INTEGER,
     <screen>
 MyChoice ::= CHOICE {
     untagged INTEGER,
-    tagged   &lsqb;99&rsqb; IMPLICIT INTEGER,
+    tagged   [99] IMPLICIT INTEGER,
     other    BOOLEAN
 }
     </screen>
     other    BOOLEAN
 }
     </screen>
@@ -1135,9 +1195,9 @@ typedef struct MyChoice
     } which;
     union
     {
     } which;
     union
     {
-        int *untagged;
-        int *tagged;
-        bool_t *other;
+        Odr_int *untagged;
+        Odr_int *tagged;
+        Odr_bool *other;
     } u;
 };
     </screen>
     } u;
 };
     </screen>
@@ -1149,7 +1209,7 @@ typedef struct MyChoice
     <screen>
 int myChoice(ODR o, MyChoice **p, int optional, const char *name)
 {
     <screen>
 int myChoice(ODR o, MyChoice **p, int optional, const char *name)
 {
-    static Odr_arm arm&lsqb;&rsqb; =
+    static Odr_arm arm[] =
     {
       {-1, -1, -1, MyChoice_untagged, odr_integer, "untagged"},
       {ODR_IMPLICIT, ODR_CONTEXT, 99, MyChoice_tagged, odr_integer,
     {
       {-1, -1, -1, MyChoice_untagged, odr_integer, "untagged"},
       {ODR_IMPLICIT, ODR_CONTEXT, 99, MyChoice_tagged, odr_integer,
@@ -1185,7 +1245,7 @@ int myChoice(ODR o, MyChoice **p, int optional, const char *name)
     </para>
 
     <para>
     </para>
 
     <para>
-     The ASN.1 specifictions naturally requires that each member of a
+     The ASN.1 specifications naturally requires that each member of a
      CHOICE have a distinct tag, so they can be told apart on decoding.
      Sometimes it can be useful to define a CHOICE that has multiple types
      that share the same tag. You'll need some other mechanism, perhaps
      CHOICE have a distinct tag, so they can be told apart on decoding.
      Sometimes it can be useful to define a CHOICE that has multiple types
      that share the same tag. You'll need some other mechanism, perhaps
@@ -1219,7 +1279,7 @@ void odr_choice_bias(ODR o, int what);
    </sect2>
   </sect1>
 
    </sect2>
   </sect1>
 
-  <sect1><title>Debugging</title>
+  <sect1 id="odr.debugging"><title>Debugging</title>
 
    <para>
     The protocol modules are suffering somewhat from a lack of diagnostic
 
    <para>
     The protocol modules are suffering somewhat from a lack of diagnostic
@@ -1244,7 +1304,7 @@ void odr_choice_bias(ODR o, int what);
  sgml-indent-step:1
  sgml-indent-data:t
  sgml-parent-document: "yaz.xml"
  sgml-indent-step:1
  sgml-indent-data:t
  sgml-parent-document: "yaz.xml"
- sgml-local-catalogs: "../../docbook/docbook.cat"
+ sgml-local-catalogs: nil
  sgml-namecase-general:t
  End:
  -->
  sgml-namecase-general:t
  End:
  -->