Commits

Markus Mottl  committed 3bc58b3

Merged bin-prot 2.0.7 from OCaml Forge

  • Participants
  • Parent commits 9fbfac3

Comments (0)

Files changed (29)

File base/bin-prot/Changelog

+2011-11-10:  Improved portability to older glibc distributions.
+
+2011-09-15:  Fixes to improve package dependency resolution.
+
+2011-07-04:  Internal updates to sync with Jane Street.
+
+2011-06-29:  Fixed bigstring layout bug, which should only affect value
+             comparisons with OCaml 3.12.1 or later.
+
+             Made 64-bit detection more reliable on Mac OS X.
+
 2010-03-20:  Fixed linking of toplevels to require bigarrays.
 
              Improved compilation on Mac OS X.

File base/bin-prot/LICENSE.Tywith

----------------------------------------------------------------------------
-Copyright (c) 2004 Martin Sandin
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. The name of the author may not be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
+---------------------------------------------------------------------------
+Copyright (c) 2004 Martin Sandin
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------

File base/bin-prot/README

                                         
                           README: library "Bin_prot"
                           **************************
-             Copyright   (C)   2008  Jane Street Holding, LLC (1)
-            =====================================================
+             Copyright (C) 2007-2011  Jane Street Holding, LLC (1)
+            ======================================================
                              Author: Markus Mottl 
                             ======================
-                             New York, 2007-10-12
+                             New York, 2011-07-29
                              ====================
   
 
 
    
                                         
-------------------------------------------------------------------------------
-                                      -
-|     CHANGES       |                  History of code changes               
-                                      |
-------------------------------------------------------------------------------
-                                      -
-|    COPYRIGHT      |                    Notes on copyright                  
-                                      |
-------------------------------------------------------------------------------
-                                      -
-|     INSTALL       |               Short notes on compiling and             
-                                      |
-|                   |                  installing the library                
-                                      |
-------------------------------------------------------------------------------
-                                      -
-|     LICENSE       |            "GNU LESSER GENERAL PUBLIC LICENSE"         
-                                      |
-------------------------------------------------------------------------------
-                                      -
-|  LICENSE.Tywith   |     License of Tywith, from which Sexplib is derived   
-                                      |
-------------------------------------------------------------------------------
-                                      -
-|     Makefile      |                       Top Makefile                     
-                                      |
-------------------------------------------------------------------------------
-                                      -
-|  OCamlMakefile    |            Generic Makefile for OCaml-projects         
-                                      |
-------------------------------------------------------------------------------
-                                      -
-|    OMakefile      |                     Ignore this file                   
-                                      |
-------------------------------------------------------------------------------
-                                      -
-|    README.txt     |                         This file                      
-                                      |
-------------------------------------------------------------------------------
-                                      -
-      |       lib/        |  OCaml-library for type-safe binary protocol
-                                 conversions|
-------------------------------------------------------------------------------
-                                      -
-|    lib_test/      |        Test applications for the Bin_prot-library      
-                                      |
-------------------------------------------------------------------------------
-                                      -
+      ------------------------------------------------------------------
+      |    Changelog      |           History of code changes          |
+      ------------------------------------------------------------------
+      |    COPYRIGHT      |              Notes on copyright            |
+      ------------------------------------------------------------------
+      |     INSTALL       |         Short notes on compiling and       |
+      |                   |            installing the library          |
+      ------------------------------------------------------------------
+      |     LICENSE       |           License of this library          |
+      ------------------------------------------------------------------
+      |  LICENSE.Tywith   |              License of Tywith             |
+      ------------------------------------------------------------------
+      |     Makefile      |                 Top Makefile               |
+      ------------------------------------------------------------------
+      |    README.txt     |          This text in ASCII format         |
+      ------------------------------------------------------------------
+      |       doc/        |         LaTeX sources for this text        |
+      ------------------------------------------------------------------
+      |       lib/        |               Library sources              |
+      ------------------------------------------------------------------
+      |    lib_test/      |  Test applications for the Bin_prot-library|
+      ------------------------------------------------------------------
+      |     syntax/       |      Preprocessor for type definitions     |
+      ------------------------------------------------------------------
                                         
   
   
 
   
   This library contains functionality for reading and writing OCaml-values in
-a type-safe binary protocol. These functions are extremely efficient and
-provide users with a convenient and safe way of performing I/O on any
-extensionally defined data type. This means that functions, objects, and
-values whose type is bound through a polymorphic record field are not
-supported, but everything else is.
+a type-safe binary protocol. It is extremely efficient, typically supporting
+type-safe marshalling and unmarshalling of even highly structured values at
+speeds sufficient to saturate a gigabit connection. The protocol is also
+heavily optimized for size, making it ideal for long-term storage of large
+amounts of data.
+   The library is highly dependable and safe to use: a rigorous test suite has
+to date guaranteed that this library has never exhibited a bug in production
+systems in several years of use. "Bin_prot" has been successfully employed in
+mission-critical financial applications, storing many terabytes of structured
+data derived from thousands of type definitions, and typically processing
+millions of messages a day in realtime for low-latency applications that must
+not crash.
+   Since version two this library should work with all CPU architectures
+currently supported by OCaml, no matter the word size (32 or 64 bit),
+endianness (2), or alignment requirements. It provides users with a convenient
+and safe way of performing I/O on any extensionally defined OCaml type (see
+later sections for details). Functions, objects, first-class modules, as well
+as values whose type is bound through a polymorphic record field are hence not
+supported. This is hardly ever a limitation in practice.
    As of now, there is no support for cyclic or shared values. Cyclic values
-will lead to non-termination whereas shared values, besides requiring
-significantly more space when encoded, may lead to a substantial increase in
-memory footprint when they are read back in.
-  Currently only little endian (2) computer architectures are supported. Some
-architectures may potentially also suffer from data alignment issues with this
-library. Only Intel architectures are currently well-tested. Both 32bit and
-64bit architectures are fully supported.
+will lead to non-termination whereas shared values, besides requiring more
+space when encoded, may lead to a substantial increase in memory footprint
+when they are read back. It would not be trivial to support these kinds of
+values in a type-safe way without noticably sacrificing performance. If these
+kinds of values are needed, the user may want to use the as of today still
+unsafe marshalling functions provided by OCaml.
+   This library uses the machine stack for efficiency reasons. This can
+potentially lead to a crash if the stack limit is reached. Note that this is
+also a limitation of the (unsafe) standard marshalling functions shipped with
+OCaml. This problem can happen for large amounts of data if recursion in the
+type definition of the datastructure is not limited to the last element. Only
+in the latter case will tail-recursion allow for (practically) unlimited
+amounts of data. If this exceedingly rare limitation ever turned out to be an
+issue in a user application, it can often be solved by redefining the datatype
+to allow for tail-recursion. The limitation cannot be eliminated in this
+library without significant performance impact and increased complexity.
   
 
 3  How can you use it?
 values, this module is probably the most efficient and convenient for doing
 this.
    Otherwise you should annotate your type definitions to generate type
-converters automatically (see below). The preprocessor in 'pa_bin_prot.ml'
-will then generate highly optimized functions for converting your OCaml-values
-to and from the binary representation. This automatically generated code will
-use functions in 'unsafe_common', 'unsafe_read_c' and 'unsafe_write_c', which
-handle the basic types with very low-level representations for efficiency.
+converters automatically (see later sections for details). The preprocessor in
+'pa_bin_prot.ml' will then generate highly optimized functions for converting
+your OCaml-values to and from the binary representation. This automatically
+generated code will use functions in modules 'Unsafe_common', 'Unsafe_read_c'
+and 'Unsafe_write_c', which employ unsafe internal representations to achieve
+this performance. The auto-generated code is extremely well-tested and should
+use these unsafe representations correctly. Developers who want to make manual
+use of these unsafe calling conventions for efficiency are strongly encouraged
+to test their code carefully.
    The module 'Size' allows you to compute the size of basic OCaml-values in
 the binary representations before writing them to a buffer. The code generator
 will also provide you with functions for your user-defined types.
-   The modules 'Read_c' and 'Write_c' wrap the low-level converters for basic
-values to ones accessible easily in OCaml and vice versa, and export functions
-for wrapping user-defined converters. This should make it easy to add
-user-defined converters that interact with a specific representation, but you
-want to make them available to the other one quickly. The test applications in
-the distribution make use of these wrappers to verify the correctness of
-implementations for low-level (C) and high-level (OCaml) representations.
+   Module 'Std' predefines converters for most standard OCaml types. If you
+use the preprocessor macros to generate code from type definitions, make sure
+that the contents of this module is visible by e.g. adding the following at
+the top of files using this library:
+   
+<<  open Bin_prot.Std
+>>
+  
+  Note that you can shadow the definitions in the above module in the unlikely
+event that the predefined ways of converting data are unsatisfactory to you.
+   The modules 'Read_c' and 'Write_c' wrap the unsafe low-level converters for
+basic values to ones accessible safely from within OCaml and vice versa. They
+also export functions for wrapping user-defined converters. This should help
+developers make their converters available in the respective other
+representation (low- or high-level). The test applications in the distribution
+use these wrappers to verify the correctness of implementations for low-level
+(C) and high-level (OCaml) representations.
    The module 'Type_class' contains some extra definitions for type classes of
 basic values. These definitions can be passed to the function 'bin_dump' in
 module 'Utils' to marshal values into buffers of exact size using the binary
 protocol. However, if bounds on the size of values are known, it is usually
 more efficient to write them directly into preallocated buffers and just catch
-exceptions if the buffer limits are hit. That way one does not have to compute
-the size of the value, which can sometimes be almost as expensive as writing
-the value in the first place.
-   The module 'Utils.ReadBuf' can be used to very efficiently read
-size-prefixed values as written by 'bin_dump' with the 'header_size' flag.
-This works even in the presence of partial data, e.g. when reading from
-streaming data coming from sockets, etc. In most cases, when a whole value
-fits into a buffer, this module will parse directly from the original buffer
-and only copy data to an internal one on partial reads.
+exceptions if the buffer limits are unexpectedly violated. Doing so should
+never cause a crash. That way one does not have to compute the size of the
+value, which can sometimes be almost as expensive as writing the value in the
+first place.
+   In module 'Utils' the function 'bin_read_stream' can be used to efficiently
+read size-prefixed values as written by 'bin_dump' there with the 'header'
+flag set to 'true'. This module also offers several useful functors. The ones
+for 'binable' types help users create readers and writers if a type needs to
+be converted to or from some intermediate representation before marshalling or
+after unmarshalling respectively. The functors for 'iterable' types are
+helpful if some (usually abstract) datatype offers iteration over elements and
+if the series of iterated-over elements alone is sufficient to reconstruct the
+original value. This allows for a more compact protocol and for robustness
+against changes to the internal representation of the datatype (e.g. sets,
+maps, etc.).
   
 
 3.1  Examples
 =============
   
   E.g. given the following type definition:
+   
 <<  type t = A | B
     with bin_io
 >>
   
-  The above will generate the functions 'bin_size_t', 'bin_write_t',
-'bin_read_t', and the type class values 'bin_writer_t', 'bin_reader_t' and
-'bin_rw_t' . If you use the annotation 'bin_write' instead of 'bin_io', then
-only the write and size functions and their type class will be generated.
-Specifying 'bin_read' will generate the read functions and associated type
-class only. 'bin_type_class' will generate the combined type class only, thus
-allowing the user to easily define their own reader and writer type classes.
-The code generator may also generate low-level entry points used for
+  This will generate functions 'bin_size_t', 'bin_write_t', and 'bin_read_t'.
+Furthermore the type class values 'bin_writer_t', 'bin_reader_t' and 'bin_t'.
+If you use the annotation 'bin_write' instead of 'bin_io', then only the write
+and size functions and their type class will be generated. Specifying
+'bin_read' will generate the read functions and associated type class only.
+The annotation 'bin_type_class' will generate the combined type class only,
+thus allowing the user to easily define their own reader and writer type
+classes. The code generator may also generate low-level entry points used for
 efficiency or backtracking.
   
   The preprocessor can also generate signatures for conversion functions. Just
 
   
   The binary protocol does not contain any data other than the minimum needed
-to decode written out values. This means that the user is responsible for e.g.
-writing out the size of messages themselves if they want to be able to
-preallocate sufficiently sized buffers before reading.
+to decode values. This means that the user is responsible for e.g. writing out
+the size of messages themselves if they want to be able to preallocate
+sufficiently sized buffers before reading. The 'Utils' module provides some
+simple functions for that matter, though users may obtain optimum efficiency
+by managing buffers themselves.
    The basic OCaml-values are written out character-wise as described below
 using hex codes for the character encoding. Some of these values require
 size/length information to be written out before the value (e.g. for lists,
 hash tables, strings, etc.). Size information is always encoded as natural
-numbers ('Nat0.t').
+numbers ('Nat0.t'). The little-endian format is used in the protocol for the
+contents of integers on all platforms.
    The following definitions will be used in the encoding specifications
 below:
   
    - n <= 65536 -> the integer associated with the tag is written out as two
    characters (lower 16 bits). 
   
-  Arguments to the tag are written out in the order of occurrence without any
-extra information.
+  Sum types with more tags are currently not supported and highly unlikely to
+occur in practice. Arguments to the tag are written out in the order of
+occurrence without any extra information.
   
 
 4.12  Polymorphic variants
 ==========================
   
   The tags of these values are written out as four characters, more precisely
-as the 32 bit hash value computed by OCaml for the given tag. Any arguments
-associated with the tag are written out afterwards in the order of occurrence
-without any extra information. When polymorphic variants are being read, they
-will be matched in order of occurrence (left-to-right) in the type and
-depth-first in the case of included polymorphic types. The first type
-containing a match for the variant will be used for reading.
+as the 32 bit hash value computed by OCaml for the given tag in little-endian
+format. Any arguments associated with the tag are written out afterwards in
+the order of occurrence without any extra information.
+   When polymorphic variants are being read, they will be matched in order of
+occurrence (left-to-right) in the type and depth-first in the case of included
+polymorphic types. The first type containing a match for the variant will be
+used for reading. Note that this only matters if semantic invariants are used
+that may impose constraints on whether a value is legal. It is strongly
+suggested to not use different constraints for polymorphic variants with the
+same representation if it is used within the same type, since this is
+inconsistent and hence confusing.
   
 
 4.13  Lists and arrays
   
   First the size of the hash table is written out as 'Nat0.t'. Then the writer
 iterates over each binding in the hash table and writes out the key followed
-by the value without any extra information.
+by the value without any extra information. Note that this makes reading
+somewhat slower than if we used the internal (extensional) representation of
+the hash table, because all values have to be rehashed. On the other hand, the
+format becomes more robust in case the hash table implementation changes.
   
 
-4.15  Bigarrays
-===============
+4.15  Bigarrays of doubles and characters
+=========================================
   
   First the dimension(s) are written out as 'Nat0.t'. Then the contents is
 copied verbatim.
 4.17  Abstract datatypes
 ========================
   
-  If you want to convert an abstract datatype, you will have to roll your own
-conversion functions. Use the functions in module 'Read_c' and 'Write_c' to
-map between low-level and high-level representations, or implement those
-manually for maximum efficiency.
+  If you want to convert an abstract datatype that may impose constraints on
+the well-formedness of values, you will have to roll your own conversion
+functions. Use the functions in module 'Read_c' and 'Write_c' to map between
+low-level and high-level representations, or implement those manually for
+maximum efficiency. The 'Utils' module may also come in handy as described in
+earlier sections, e.g. if the value can be converted to and from an
+intermediate representation that does not impose constraints, or if some sort
+of iteration is supported by the datatype.
   
 
 5  Contact information
   
  (1) http://www.janestreet.com
  
- (2) Endianness defines the byte order in which machine representations for
-   integers and floating point numbers are written to main memory
+ (2) Endianness defines the byte order in which machine representations of
+   integers are stored in main memory.
  
  (3) Only supported on 64 bit platforms.
  

File base/bin-prot/doc/README.tex

 \newcommand{\ocsrc}[2]{\athome{ocaml/#1}{#2}}
 \newcommand{\myocsrc}[1]{\athome{ocaml/#1}{#1}}
 
-\newcommand{\janeshort}{\ahref{http://www.janestreet.com} {Jane Street Holding, LLC}}
+\newcommand{\janeshort}{\ahref{http://www.janestreet.com}{Jane Street Holding, LLC}}
 
 \newcommand{\trow}[2]{\quad #1 \quad&\quad #2 \quad\\}
 \newcommand{\trowl}[2]{\trow{#1}{#2}\hline}
 
 \title{README: library ``Bin\_prot''}
 \author{
-  Copyright \quad (C) \quad \theyear \quad \janeshort \quad\\
+  Copyright (C) 2007-\theyear \quad \janeshort\\
   Author: Markus Mottl
 }
-\date{New York, 2007-10-12}
+\date{New York, 2011-07-29}
 
 % DOCUMENT
 \begin{document}
 \begin{center}
 \begin{tabular}{|c|c|}
 \hline
-\trowl{CHANGES}{History of code changes}
+\trowl{Changelog}{History of code changes}
 \trowl{COPYRIGHT}{Notes on copyright}
 \trow{INSTALL}{Short notes on compiling and}
 \trowl{}{installing the library}
-\trowl{LICENSE}{``GNU LESSER GENERAL PUBLIC LICENSE''}
-\trowl{LICENSE.Tywith}{License of Tywith, from which Bin-prot is derived}
+\trowl{LICENSE}{License of this library}
+\trowl{LICENSE.Tywith}{License of Tywith}
 \trowl{Makefile}{Top Makefile}
-\trowl{OCamlMakefile}{Generic Makefile for OCaml-projects}
-\trowl{OMakefile}{Ignore this file}
-\trowl{README.txt}{This file}
-\trowl{lib/}{OCaml-library for type-safe binary protocol conversions}
+\trowl{README.txt}{This text in ASCII format}
+\trowl{doc/}{LaTeX sources for this text}
+\trowl{lib/}{Library sources}
 \trowl{lib\_test/}{Test applications for the Bin\_prot-library}
+\trowl{syntax/}{Preprocessor for type definitions}
 \end{tabular}
 \end{center}
 
 \section{What is ``Bin\_prot''}
 
-This library contains functionality for reading and writing OCaml-values
-in a type-safe binary protocol.  These functions are extremely efficient
-and provide users with a convenient and safe way of performing I/O on any
-extensionally defined data type.  This means that functions, objects,
-and values whose type is bound through a polymorphic record field are
-not supported, but everything else is.\\
+This library contains functionality for reading and writing OCaml-values in a
+type-safe binary protocol.  It is extremely efficient, typically supporting
+type-safe marshalling and unmarshalling of even highly structured values at
+speeds sufficient to saturate a gigabit connection.  The protocol is also
+heavily optimized for size, making it ideal for long-term storage of large
+amounts of data.\\
 
-As of now, there is no support for cyclic or shared values.
-Cyclic values will lead to non-termination whereas shared values,
-besides requiring significantly more space when encoded, may lead to
-a substantial increase in memory footprint when they are read back in.
+The library is highly dependable and safe to use: a rigorous test suite has
+to date guaranteed that this library has never exhibited a bug in production
+systems in several years of use.  ``Bin\_prot'' has been successfully
+employed in mission-critical financial applications, storing many terabytes
+of structured data derived from thousands of type definitions, and typically
+processing millions of messages a day in realtime for low-latency applications
+that must not crash.\\
 
-Currently only little endian\footnote{Endianness defines the byte
-order in which machine representations for integers and floating point
-numbers are written to main memory} computer architectures are supported.
-Some architectures may potentially also suffer from data alignment issues
-with this library.  Only Intel architectures are currently well-tested.
-Both 32bit and 64bit architectures are fully supported.
+Since version two this library should work with all CPU architectures
+currently supported by OCaml, no matter the word size (32 or 64 bit),
+endianness\footnote{Endianness defines the byte order in which machine
+representations of integers are stored in main memory.}, or alignment
+requirements.  It provides users with a convenient and safe way of performing
+I/O on any extensionally defined OCaml type (see later sections for details).
+Functions, objects, first-class modules, as well as values whose type is
+bound through a polymorphic record field are hence not supported.  This is
+hardly ever a limitation in practice.\\
+
+As of now, there is no support for cyclic or shared values.  Cyclic values
+will lead to non-termination whereas shared values, besides requiring more
+space when encoded, may lead to a substantial increase in memory footprint
+when they are read back.  It would not be trivial to support these kinds
+of values in a type-safe way without noticably sacrificing performance.
+If these kinds of values are needed, the user may want to use the as of
+today still unsafe marshalling functions provided by OCaml.\\
+
+This library uses the machine stack for efficiency reasons.  This can
+potentially lead to a crash if the stack limit is reached.  Note that this
+is also a limitation of the (unsafe) standard marshalling functions shipped
+with OCaml.  This problem can happen for large amounts of data if recursion in
+the type definition of the datastructure is not limited to the last element.
+Only in the latter case will tail-recursion allow for (practically) unlimited
+amounts of data.  If this exceedingly rare limitation ever turned out to
+be an issue in a user application, it can often be solved by redefining the
+datatype to allow for tail-recursion.  The limitation cannot be eliminated in
+this library without significant performance impact and increased complexity.
 
 \section{How can you use it?}
 
-The API (.mli-files) in the library directory is fully documented.
-Module \verb=Common= defines some globally used types, functions, exceptions,
+The API (.mli-files) in the library directory is fully documented.  Module
+\verb=Common= defines some globally used types, functions, exceptions,
 and values.  \verb=Nat0= implements natural numbers including zero.\\
 
 Modules \verb=Read_ml= and \verb=Write_ml= contain read and write functions
-respectively for all basic types and are implemented in OCaml as
-far as reasonable.  If you only want to read or write single, basic,
-unstructured values, this module is probably the most efficient and
-convenient for doing this.\\
+respectively for all basic types and are implemented in OCaml as far as
+reasonable.  If you only want to read or write single, basic, unstructured
+values, this module is probably the most efficient and convenient for
+doing this.\\
 
-Otherwise you should annotate your type definitions to generate
-type converters automatically (see below).  The preprocessor in
-\verb=pa_bin_prot.ml= will then generate highly optimized functions for
-converting your OCaml-values to and from the binary representation.  This
-automatically generated code will use functions in \verb=unsafe_common=,
-\verb=unsafe_read_c= and \verb=unsafe_write_c=, which handle the basic
-types with very low-level representations for efficiency.\\
+Otherwise you should annotate your type definitions to generate type
+converters automatically (see later sections for details).  The preprocessor
+in \verb=pa_bin_prot.ml= will then generate highly optimized functions
+for converting your OCaml-values to and from the binary representation.
+This automatically generated code will use functions in modules
+\verb=Unsafe_common=, \verb=Unsafe_read_c= and \verb=Unsafe_write_c=,
+which employ unsafe internal representations to achieve this performance.
+The auto-generated code is extremely well-tested and should use these unsafe
+representations correctly.  Developers who want to make manual use of these
+unsafe calling conventions for efficiency are strongly encouraged to test
+their code carefully.\\
 
-The module \verb=Size= allows you to compute the size of basic
-OCaml-values in the binary representations before writing them to
-a buffer.  The code generator will also provide you with functions for
-your user-defined types.\\
+The module \verb=Size= allows you to compute the size of basic OCaml-values
+in the binary representations before writing them to a buffer.  The code
+generator will also provide you with functions for your user-defined types.\\
 
-The modules \verb=Read_c= and \verb=Write_c= wrap the low-level converters
-for basic values to ones accessible easily in OCaml and vice versa, and
-export functions for wrapping user-defined converters.  This should make
-it easy to add user-defined converters that interact with a specific
-representation, but you want to make them available to the other one
-quickly.  The test applications in the distribution make use of these
-wrappers to verify the correctness of implementations for low-level (C)
-and high-level (OCaml) representations.\\
+Module \verb=Std= predefines converters for most standard OCaml types.
+If you use the preprocessor macros to generate code from type definitions,
+make sure that the contents of this module is visible by e.g.\ adding the
+following at the top of files using this library:\\
+
+\begin{verbatim}
+  open Bin_prot.Std
+\end{verbatim}
+
+Note that you can shadow the definitions in the above module in the unlikely
+event that the predefined ways of converting data are unsatisfactory to you.\\
+
+The modules \verb=Read_c= and \verb=Write_c= wrap the unsafe low-level
+converters for basic values to ones accessible safely from within OCaml and
+vice versa.  They also export functions for wrapping user-defined converters.
+This should help developers make their converters available in the respective
+other representation (low- or high-level).  The test applications in the
+distribution use these wrappers to verify the correctness of implementations
+for low-level (C) and high-level (OCaml) representations.\\
 
 The module \verb=Type_class= contains some extra definitions for type
 classes of basic values.  These definitions can be passed to the function
-\verb=bin_dump= in module \verb=Utils= to marshal values into buffers
-of exact size using the binary protocol.  However, if bounds on the size
-of values are known, it is usually more efficient to write them directly
-into preallocated buffers and just catch exceptions if the buffer limits
-are hit.  That way one does not have to compute the size of the value,
-which can sometimes be almost as expensive as writing the value in the
-first place.\\
+\verb=bin_dump= in module \verb=Utils= to marshal values into buffers of
+exact size using the binary protocol.  However, if bounds on the size of
+values are known, it is usually more efficient to write them directly into
+preallocated buffers and just catch exceptions if the buffer limits are
+unexpectedly violated.  Doing so should never cause a crash.  That way one
+does not have to compute the size of the value, which can sometimes be almost
+as expensive as writing the value in the first place.\\
 
-The module \verb=Utils.ReadBuf= can be used to very efficiently
-read size-prefixed values as written by \verb=bin_dump= with the
-\verb=header_size= flag.  This works even in the presence of partial
-data, e.g.\ when reading from streaming data coming from sockets, etc.
-In most cases, when a whole value fits into a buffer, this module will
-parse directly from the original buffer and only copy data to an internal
-one on partial reads.
+In module \verb=Utils= the function \verb=bin_read_stream= can be used
+to efficiently read size-prefixed values as written by \verb=bin_dump=
+there with the \verb=header= flag set to \verb=true=.  This module also
+offers several useful functors.  The ones for \verb=binable= types help
+users create readers and writers if a type needs to be converted to or from
+some intermediate representation before marshalling or after unmarshalling
+respectively.  The functors for \verb=iterable= types are helpful if some
+(usually abstract) datatype offers iteration over elements and if the series of
+iterated-over elements alone is sufficient to reconstruct the original value.
+This allows for a more compact protocol and for robustness against changes
+to the internal representation of the datatype (e.g.\ sets, maps, etc.).
 
 \subsection{Examples}
 
-E.g. given the following type definition:
+E.g. given the following type definition:\\
 
 \begin{verbatim}
   type t = A | B
   with bin_io
 \end{verbatim}
 
-The above will generate the functions \verb=bin_size_t=,
-\verb=bin_write_t=, \verb=bin_read_t=, and the type class values
-\verb=bin_writer_t=, \verb=bin_reader_t= and \verb=bin_rw_t= .  If you
-use the annotation \verb=bin_write= instead of \verb=bin_io=, then only
-the write and size functions and their type class will be generated.
-Specifying \verb=bin_read= will generate the read functions and associated
-type class only.  \verb=bin_type_class= will generate the combined type
-class only, thus allowing the user to easily define their own reader
-and writer type classes.  The code generator may also generate low-level
-entry points used for efficiency or backtracking.\\
-\\
-The preprocessor can also generate signatures for conversion functions.
-Just add the wanted annotation to the type in a module signature for
-that purpose.
+This will generate functions \verb=bin_size_t=, \verb=bin_write_t=, and
+\verb=bin_read_t=.  Furthermore the type class values \verb=bin_writer_t=,
+\verb=bin_reader_t= and \verb=bin_t=.  If you use the annotation
+\verb=bin_write= instead of \verb=bin_io=, then only the write and size
+functions and their type class will be generated.  Specifying \verb=bin_read=
+will generate the read functions and associated type class only.
+The annotation \verb=bin_type_class= will generate the combined type class
+only, thus allowing the user to easily define their own reader and writer
+type classes.  The code generator may also generate low-level entry points
+used for efficiency or backtracking.\\ \\ The preprocessor can also generate
+signatures for conversion functions.  Just add the wanted annotation to the
+type in a module signature for that purpose.
 
 \section{Specification of the Binary Protocol}
 
-The binary protocol does not contain any data other than the minimum
-needed to decode written out values.  This means that the user is
-responsible for e.g.\ writing out the size of messages themselves if
-they want to be able to preallocate sufficiently sized buffers before
-reading.\\
+The binary protocol does not contain any data other than the minimum needed
+to decode values.  This means that the user is responsible for e.g.\
+writing out the size of messages themselves if they want to be able to
+preallocate sufficiently sized buffers before reading.  The \verb=Utils=
+module provides some simple functions for that matter, though users may
+obtain optimum efficiency by managing buffers themselves.\\
 
 The basic OCaml-values are written out character-wise as described below
 using hex codes for the character encoding.  Some of these values require
-size/length information to be written out before the value (e.g.\ for
-lists, hash tables, strings, etc.).  Size information is always encoded
-as natural numbers (\verb=Nat0.t=).\\
+size/length information to be written out before the value (e.g.\ for lists,
+hash tables, strings, etc.).  Size information is always encoded as natural
+numbers (\verb=Nat0.t=).  The little-endian format is used in the protocol
+for the contents of integers on all platforms.\\
 
-\noindent The following definitions will be used in the encoding
-specifications below:
+\noindent The following definitions will be used in the encoding specifications
+below:
 
 \begin{itemize}
 \item \verb=CODE_NEG_INT8= $\rightarrow$ \verb=0xff=
 
 Appropriate exceptions will be raised if there is an overflow, e.g.\ if
 a 64 bit encoding is read on a 32 bit platform, or if the 32 bit or 64
-bit encoding overflowed the 30 bit or 62 bit capacity\footnote{One
-bit is reserved by OCaml for GC-tagging, and the sign bit is lost.}
-of natural numbers on their respective platforms.
+bit encoding overflowed the 30 bit or 62 bit capacity\footnote{One bit is
+reserved by OCaml for GC-tagging, and the sign bit is lost.} of natural
+numbers on their respective platforms.
 
 \subsection{Unit values}
 
 
 \subsection{Strings}
 
-First the length of the string is written out as a \verb=Nat0.t=.
-Then the contents of the string is copied verbatim.
+First the length of the string is written out as a \verb=Nat0.t=.  Then the
+contents of the string is copied verbatim.
 
 \subsection{Characters}
 
 \item $<$ \verb=-0x80000000= $\rightarrow$ \verb=CODE_INT64= followed by all 64 bits of integer.
 \end{itemize}
 
-All of the above branches will be considered when converting values
-of type \verb=int64=.  The case for \verb=CODE_INT64= will only be
-considered with types \verb=int= and \verb=nativeint= if the architecture
-supports it.  \verb=int32= will never be encoded as a \verb=CODE_INT64=.
-Appropriate exceptions will be raised if the architecture of or the type
-requested by the reader does not support some encoding, or if there
-is an overflow\footnote{An overflow can only happen with int values:
-one bit is reserved by OCaml for the GC-tag.}.
+All of the above branches will be considered when converting values of
+type \verb=int64=.  The case for \verb=CODE_INT64= will only be considered
+with types \verb=int= and \verb=nativeint= if the architecture supports it.
+\verb=int32= will never be encoded as a \verb=CODE_INT64=.  Appropriate
+exceptions will be raised if the architecture of or the type requested by the
+reader does not support some encoding, or if there is an overflow\footnote{An
+overflow can only happen with int values: one bit is reserved by OCaml for
+the GC-tag.}.
 
 \subsection{Floats}
 
 
 \subsection{References and lazy values}
 
-Same as the binary encoding of the value in the reference or of the
-value calculated lazily.
+Same as the binary encoding of the value in the reference or of the value
+calculated lazily.
 
 \subsection{Option values}
 
 
 \subsection{Tuples and records}
 
-Values in tuples and records are written out one after the other in
-the order as specified in the type specification without any extra
-information.  Polymorphic record fields are supported unless a value
-of the type bound by the field were accessed, which would lead to an
-exception.
+Values in tuples and records are written out one after the other in the
+order as specified in the type specification without any extra information.
+Polymorphic record fields are supported unless a value of the type bound by
+the field were accessed, which would lead to an exception.
 
 \subsection{Sum types}
 
-Each tag is assigned an integer from $0$ to $n - 1$ in exactly the same
-order as they occur in the type, where $n$ is the number of sum tags in
-the type.  If a value of this type needs to be written out, then if:
+Each tag is assigned an integer from $0$ to $n - 1$ in exactly the same order
+as they occur in the type, where $n$ is the number of sum tags in the type.
+If a value of this type needs to be written out, then if:
 
 \begin{itemize}
 \item $n \leq 256 \rightarrow$ the integer associated with the tag is written out as one character (lower 8 bits).
 \item $n \leq 65536 \rightarrow$ the integer associated with the tag is written out as two characters (lower 16 bits).
 \end{itemize}
 
-Arguments to the tag are written out in the order of occurrence without
-any extra information.
+Sum types with more tags are currently not supported and highly unlikely
+to occur in practice.  Arguments to the tag are written out in the order of
+occurrence without any extra information.
 
 \subsection{Polymorphic variants}
 
 The tags of these values are written out as four characters, more
-precisely as the 32 bit hash value computed by OCaml for the given tag.
-Any arguments associated with the tag are written out afterwards in the
-order of occurrence without any extra information.  When polymorphic
-variants are being read, they will be matched in order of occurrence
-(left-to-right) in the type and depth-first in the case of included
-polymorphic types.  The first type containing a match for the variant
-will be used for reading.
+precisely as the 32 bit hash value computed by OCaml for the given tag in
+little-endian format.  Any arguments associated with the tag are written
+out afterwards in the order of occurrence without any extra information.\\
+
+When polymorphic variants are being read, they will be matched in order
+of occurrence (left-to-right) in the type and depth-first in the case of
+included polymorphic types.  The first type containing a match for the
+variant will be used for reading.  Note that this only matters if semantic
+invariants are used that may impose constraints on whether a value is legal.
+It is strongly suggested to not use different constraints for polymorphic
+variants with the same representation if it is used within the same type,
+since this is inconsistent and hence confusing.
 
 \subsection{Lists and arrays}
 
-For lists and arrays the length is written out as a \verb=Nat0.t=
-first, followed by all values in the same order as in the datastructure
-without any extra information.
+For lists and arrays the length is written out as a \verb=Nat0.t= first,
+followed by all values in the same order as in the datastructure without
+any extra information.
 
 \subsection{Hash tables}
 
-First the size of the hash table is written out as \verb=Nat0.t=.
-Then the writer iterates over each binding in the hash table and writes
-out the key followed by the value without any extra information.
+First the size of the hash table is written out as \verb=Nat0.t=.  Then the
+writer iterates over each binding in the hash table and writes out the
+key followed by the value without any extra information.  Note that this
+makes reading somewhat slower than if we used the internal (extensional)
+representation of the hash table, because all values have to be rehashed.
+On the other hand, the format becomes more robust in case the hash table
+implementation changes.
 
-\subsection{Bigarrays}
+\subsection{Bigarrays of doubles and characters}
 
-First the dimension(s) are written out as \verb=Nat0.t=.  Then the
-contents is copied verbatim.
+First the dimension(s) are written out as \verb=Nat0.t=.  Then the contents
+is copied verbatim.
 
 \subsection{Polymorphic values}
 
   type foo = int t with bin_io
 \end{verbatim}
 
-In the above case the conversion functions will behave as if \verb=foo=
-had been defined as a monomorphic version of \verb=t= with \verb='a=
-replaced by \verb=int= on the right hand side.
+In the above case the conversion functions will behave as if \verb=foo= had
+been defined as a monomorphic version of \verb=t= with \verb='a= replaced
+by \verb=int= on the right hand side.
 
 \subsection{Abstract datatypes}
 
-If you want to convert an abstract datatype, you will have to roll your
-own conversion functions.  Use the functions in module \verb=Read_c= and
-\verb=Write_c= to map between low-level and high-level representations,
-or implement those manually for maximum efficiency.
+If you want to convert an abstract datatype that may impose constraints on
+the well-formedness of values, you will have to roll your own conversion
+functions.  Use the functions in module \verb=Read_c= and \verb=Write_c=
+to map between low-level and high-level representations, or implement those
+manually for maximum efficiency.  The \verb=Utils= module may also come in
+handy as described in earlier sections, e.g.\ if the value can be converted
+to and from an intermediate representation that does not impose constraints,
+or if some sort of iteration is supported by the datatype.
 
 \section{Contact information}
 
-\noindent In the case of bugs, feature requests and similar, you can
-contact us here:\\\\
+\noindent In the case of bugs, feature requests and similar, you can contact
+us here:\\\\
 
 \hspace{2ex}\mail\\\\
 
-\noindent Up-to-date information concerning this library should be
-available here:\\\\
+\noindent Up-to-date information concerning this library should be available
+here:\\\\
 
 \hspace{2ex}\homeurl/ocaml\\\\
 

File base/bin-prot/lib/TODO

-support big endian platforms by forcing little endianness on them
-
-testing:
+Testing:
 
   bin_write_int_{8,16,32,64}bit
   bin_size_...

File base/bin-prot/lib/common.mli

-(** common definitions used by binary protocol converters *)
+(** Common definitions used by binary protocol converters *)
 
 open Bigarray
 

File base/bin-prot/lib/common_stubs.h

 #ifndef COMMON_STUBS_H
 #define COMMON_STUBS_H
 
+#define _BSD_SOURCE
+#include <sys/types.h>
+
 #include <string.h>
 #include <arpa/inet.h>
 
 #include <caml/callback.h>
 #include <caml/signals.h>
 
+#ifdef ARCH_INT64_TYPE
+#include "int64_native.h"
+#else
+#include "int64_emul.h"
+#endif
 
-/* Portable byte swapping */
 
+/* Endianness- and alignment-independent integer marshalling functions */
+
+#define le8dec(x) (*x)
+
+#ifndef le16dec  /* FreeBSD marshalling functions not available */
+
+#ifdef OS_DARWIN
+/* Darwin platform */
+#include <libkern/OSByteOrder.h>
+
+#define le16dec(ptr) OSReadLittleInt16(ptr, 0)
+#define le32dec(ptr) OSReadLittleInt32(ptr, 0)
+#define le64dec(ptr) OSReadLittleInt64(ptr, 0)
+
+#define be16dec(ptr) OSReadBigInt16(ptr, 0)
+#define be32dec(ptr) OSReadBigInt32(ptr, 0)
+#define be64dec(ptr) OSReadBigInt64(ptr, 0)
+
+#define le16enc(ptr, n) OSWriteLittleInt16(ptr, 0, n)
+#define le32enc(ptr, n) OSWriteLittleInt32(ptr, 0, n)
+#define le64enc(ptr, n) OSWriteLittleInt64(ptr, 0, n)
+
+#define be16enc(ptr, n) OSWriteBigInt16(ptr, 0, n)
+#define be32enc(ptr, n) OSWriteBigInt32(ptr, 0, n)
+#define be64enc(ptr, n) OSWriteBigInt64(ptr, 0, n)
+
+#else
+
+/* Non-Darwin platform */
+/* Emulate with memcpy and endianness conversion functions */
+
+/* Define BSD conversion functions if undefined */
+#ifndef le16toh
+
+/* Define portable byte swapping if undefined */
+/* WARNING: will not work on mixed endian machines! */
+/* WARNING: these functions must be defined by the system in the above case */
 #ifndef bswap_16
 #define bswap_16(value) \
   (((uint16_t) ((value) & 0xff) << 8) | ((uint16_t) (value) >> 8))
     (uint64_t) bswap_32(((value) >> 32)))
 #endif
 
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+/* Little-endian architecture */
+#define htobe16(x) bswap_16 (x)
+#define htole16(x) (x)
+#define be16toh(x) bswap_16 (x)
+#define le16toh(x) (x)
+
+#define htobe32(x) bswap_32 (x)
+#define htole32(x) (x)
+#define be32toh(x) bswap_32 (x)
+#define le32toh(x) (x)
+
+#define htobe64(x) bswap_64 (x)
+#define htole64(x) (x)
+#define be64toh(x) bswap_64 (x)
+#define le64toh(x) (x)
+#else
+/* Big-endian architecture */
+#define htobe16(x) (x)
+#define htole16(x) bswap_16 (x)
+#define be16toh(x) (x)
+#define le16toh(x) bswap_16 (x)
+
+#define htobe32(x) (x)
+#define htole32(x) bswap_32 (x)
+#define be32toh(x) (x)
+#define le32toh(x) bswap_32 (x)
+
+#define htobe64(x) (x)
+#define htole64(x) bswap_64 (x)
+#define be64toh(x) (x)
+#define le64toh(x) bswap_64 (x)
+#endif  /* byte order */
+
+#endif  /* BSD conversion functions */
+
+#define le16dec(ptr) \
+  (__extension__ ({ uint16_t __n; memcpy(&__n, ptr, 2); le16toh(__n); }))
+#define le32dec(ptr) \
+  (__extension__ ({ uint32_t __n; memcpy(&__n, ptr, 4); le32toh(__n); }))
+#define le64dec(ptr) \
+  (__extension__ ({ uint64_t __n; memcpy(&__n, ptr, 8); le64toh(__n); }))
+
+#define be16dec(ptr) \
+  (__extension__ ({ uint16_t __n; memcpy(&__n, ptr, 2); be16toh(__n); }))
+#define be32dec(ptr) \
+  (__extension__ ({ uint32_t __n; memcpy(&__n, ptr, 4); be32toh(__n); }))
+#define be64dec(ptr) \
+  (__extension__ ({ uint64_t __n; memcpy(&__n, ptr, 8); be64toh(__n); }))
+
+#define le16enc(ptr, n) \
+  (__extension__ ({ uint16_t __n = htole16(n); memcpy(ptr, &__n, 2); }))
+#define le32enc(ptr, n) \
+  (__extension__ ({ uint32_t __n = htole32(n); memcpy(ptr, &__n, 4); }))
+#define le64enc(ptr, n) \
+  (__extension__ ({ uint64_t __n = htole64(n); memcpy(ptr, &__n, 8); }))
+
+#define be16enc(ptr, n) \
+  (__extension__ ({ uint16_t __n = htobe16(n); memcpy(ptr, &__n, 2); }))
+#define be32enc(ptr, n) \
+  (__extension__ ({ uint32_t __n = htobe32(n); memcpy(ptr, &__n, 4); }))
+#define be64enc(ptr, n) \
+  (__extension__ ({ uint64_t __n = htobe64(n); memcpy(ptr, &__n, 8); }))
+
+#endif  /* OS_DARWIN */
+
+#endif  /* FreeBSD marshalling functions */
+
 
 /* Bin-prot integer codes */
 

File base/bin-prot/lib/int64_emul.h

 #define I64_literal(hi,lo) { lo, hi }
 #endif
 
+#define I64_split(x,hi,lo) (hi = (x).h, lo = (x).l)
+
 /* Unsigned comparison */
 static int I64_ucompare(uint64 x, uint64 y)
 {
 }
 
 #define I64_is_zero(x) (((x).l | (x).h) == 0)
-
 #define I64_is_negative(x) ((int32) (x).h < 0)
+#define I64_is_min_int(x) ((x).l == 0 && (x).h == 0x80000000U)
+#define I64_is_minus_one(x) (((x).l & (x).h) == 0xFFFFFFFFU)
 
 /* Bitwise operations */
 static int64 I64_and(int64 x, int64 y)

File base/bin-prot/lib/int64_native.h

 #define CAML_INT64_NATIVE_H
 
 #define I64_literal(hi,lo) ((int64)(hi) << 32 | (lo))
+#define I64_split(x,hi,lo) (hi = (uint32)((x)>>32), lo = (uint32)(x))
 #define I64_compare(x,y) (((x) > (y)) - ((x) < (y)))
 #define I64_ult(x,y) ((uint64)(x) < (uint64)(y))
 #define I64_neg(x) (-(x))
 #define I64_mul(x,y) ((x) * (y))
 #define I64_is_zero(x) ((x) == 0)
 #define I64_is_negative(x) ((x) < 0)
+#define I64_is_min_int(x) ((x) == ((int64)1 << 63))
+#define I64_is_minus_one(x) ((x) == -1)
+
 #define I64_div(x,y) ((x) / (y))
 #define I64_mod(x,y) ((x) % (y))
 #define I64_udivmod(x,y,quo,rem) \

File base/bin-prot/lib/read_c.mli

-(** wrapping unsafe C-style readers to safe ML-style ones. *)
+(** Wrapping unsafe C-style readers to safe ML-style ones. *)
 
 open Common
 open Unsafe_common

File base/bin-prot/lib/read_ml.ml

   List.rev rev_lst
 
 #ifndef ARCH_SIXTYFOUR
-let dummy_float_buf = Array1.create char c_layout 8
+let dummy_float_buf = create_buf 8
 let () = ignore (Write_ml.bin_write_float dummy_float_buf ~pos:0 3.1)
 let max_array_length_2 = Sys.max_array_length / 2
 #endif

File base/bin-prot/lib/read_ml.mli

-(** reading values from the binary protocol using (mostly) OCaml. *)
+(** Reading values from the binary protocol using (mostly) OCaml. *)
 
 open Bigarray
 

File base/bin-prot/lib/read_stubs.c

     TYPE n; \
     if (unlikely(next > eptr)) \
       caml_raise_constant(*v_bin_prot_exc_Buffer_short); \
-    n = *(TYPE *) *sptr_ptr; \
+    n = le##SIZE##dec(sptr); \
     CHECK \
     *sptr_ptr = next; \
     return n; \
       *sptr_ptr = sptr - 1;
       raise_Error(READ_ERROR_NAT0_OVERFLOW);
     })
-  MK_GEN_SAFE_NAT0_READ(nocheck, 64, long, 8, {})
 #endif
 
 static inline unsigned long read_nat0(char **sptr_ptr, char *eptr)
 
 /* Reading 64bit integers */
 
-#ifdef ARCH_INT64_TYPE
-#include "int64_native.h"
-#else
-#include "int64_emul.h"
-#endif
-
 static inline int64 read_int64(char **sptr_ptr, char *eptr)
 {
   char *sptr = *sptr_ptr;
 {
   char *sptr = *sptr_ptr;
   char *next = sptr + sizeof(double);
+  double n;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
   *sptr_ptr = next;
-  return caml_copy_double(*(double *) sptr);
+  memcpy(&n, sptr, sizeof(double));
+  return caml_copy_double(n);
 }
 
 MK_ML_READER(float)
   char *next = sptr + 4;
   int n;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  n = *(int *) sptr;
+  n = le32dec(sptr);
   if (likely(Is_long(n))) {
     *sptr_ptr = next;
     return (value) n;
   if (unlikely(pos < 0)) caml_array_bound_error();
   if (unlikely(next_pos > (unsigned long) *buf->dim))
     caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  n = *(int *) sptr;
+  n = le32dec(sptr);
   if (likely(Is_long(n))) {
     Field(v_pos_ref, 0) = Val_long(next_pos);
     return (value) n;
 
 /* Reading bigarrays */
 
-#define MK_BA1_READER(NAME, TYPE, TFLAG) \
+#define MK_BA1_READER(NAME, TYPE, TFLAG, TLAYOUT) \
   CAMLprim inline value read_##NAME##_stub(char **sptr_ptr, char *eptr) \
   { \
     unsigned long len = read_nat0(sptr_ptr, eptr); \
     dim = len; \
     v_res = \
       caml_ba_alloc( \
-        CAML_BA_##TFLAG | CAML_BA_FORTRAN_LAYOUT, 1, NULL, &dim); \
+        CAML_BA_##TFLAG | CAML_BA_##TLAYOUT##_LAYOUT, 1, NULL, &dim); \
     *sptr_ptr = next; \
     if (unlikely(tot_size > 65536)) { \
       Begin_roots1(v_res); \
   \
   MK_ML_READER(NAME)
 
-MK_BA1_READER(bigstring, char, UINT8)
+MK_BA1_READER(bigstring, char, UINT8, C)
 
 #define MK_VEC_MAT_READERS(NAME, TYPE, TFLAG) \
-  MK_BA1_READER(NAME##_vec, TYPE, TFLAG) \
+  MK_BA1_READER(NAME##_vec, TYPE, TFLAG, FORTRAN) \
   \
   CAMLprim inline value read_##NAME##_mat_stub(char **sptr_ptr, char *eptr) \
   { \
   long upper;
 #endif
   char *sptr = *sptr_ptr;
-  long *lsptr = (long *) sptr;
   char *next = sptr + 8;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 #ifdef ARCH_SIXTYFOUR
-  n = *lsptr;
+  n = le64dec(sptr);
   if (unlikely(n < -0x4000000000000000L || n > 0x3FFFFFFFFFFFFFFFL))
     raise_Error(READ_ERROR_INT_OVERFLOW);
 #else
-  n = *lsptr;
-  upper = *++lsptr;
+  n = le32dec(sptr);
+  memcpy(&upper, sptr + 4, 4);
   if (upper == 0l) {
     if ((unsigned long) n > 0x3FFFFFFFl) raise_Error(READ_ERROR_INT_OVERFLOW);
   } else if (upper == -1) {
   char *next = sptr + 8;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 #ifdef ARCH_SIXTYFOUR
-  n = (*(long *) sptr);
+  n = le64dec(sptr);
 #else
-  {
-    unsigned int *uisptr = (unsigned int *) sptr;
-    unsigned int lower = *uisptr++;
-    unsigned int upper = *uisptr;
-    n = I64_or(I64_lsl(I64_of_int32(upper), 32), I64_of_int32(lower));
-  }
+  n = I64_literal(le32dec(sptr + 4), le32dec(sptr));
 #endif
   v_res = caml_copy_int64(n);
   *sptr_ptr = next;
   char *next = sptr + 2;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
   *sptr_ptr = next;
-  return (value) Val_int((uint16_t) ntohs(*((uint16_t *) sptr)));
+  return (value) Val_int(be16dec(sptr));
 }
 MK_ML_READER(network16_int)
 
   char *next = sptr + 4;
   int n;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  n = (int) ntohl(*(uint32_t *) sptr);
-#ifndef ARCH_SIXTYFOUR
+  n = (int) be32dec(sptr);
+#ifdef ARCH_SIXTYFOUR
+  *sptr_ptr = next;
+  return (value) Val_int((uint32_t) n);
+#else
   if (unlikely(n < -0x40000000l || n > 0x3FFFFFFFl))
     raise_Error(READ_ERROR_INT_OVERFLOW);
   *sptr_ptr = next;
-  return (value) Val_int((int) ntohl(*((uint32_t *) sptr)));
-#else
-  *sptr_ptr = next;
-  return (value) Val_int((uint32_t) ntohl(*((uint32_t *) sptr)));
+  return (value) Val_int(n);
 #endif
 }
 MK_ML_READER(network32_int)
   char *next = sptr + 4;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
   *sptr_ptr = next;
-  return (value) caml_copy_int32((int) ntohl(*((uint32_t *) sptr)));
+  return (value) caml_copy_int32(be32dec(sptr));
 }
 MK_ML_READER(network32_int32)
 
   long n;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 #ifdef ARCH_SIXTYFOUR
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  n = (long) bswap_64(*((uint64_t *) sptr));
-#elif __BYTE_ORDER == __BIG_ENDIAN
-  n = *((long *) sptr);
-#else
-#error "unsupported endianness"
-#endif
+  n = (long) be64dec(sptr);
   if (unlikely(n < -0x4000000000000000L || n > 0x3FFFFFFFFFFFFFFFL))
     raise_Error(READ_ERROR_INT_OVERFLOW);
 #else /* 32bit */
   /* Read the upper 32 bits first.  They must all be zero, otherwise we
      consider this an overflow.  On 32bit platforms the integer must
      fit completely into one word. */
-  n = *((long *) sptr);
+  memcpy(&n, sptr, 4);
   if (n != 0) raise_Error(READ_ERROR_INT_OVERFLOW);
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  n = (long) bswap_32(*(((uint32_t *) sptr) + 1));
-#elif __BYTE_ORDER == __BIG_ENDIAN
-  n = *(((long *) sptr) + 1);
-#else
-#error "unsupported endianness"
-#endif
+  n = be32dec(sptr + 4);
   if (unlikely(n < -0x40000000l || n > 0x3FFFFFFFl))
     raise_Error(READ_ERROR_INT_OVERFLOW);
 #endif
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
   *sptr_ptr = next;
 #ifdef ARCH_SIXTYFOUR
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  n = (long) bswap_64(*((uint64_t *) sptr));
-#elif __BYTE_ORDER == __BIG_ENDIAN
-  n = *((long *) sptr);
-#else
-#error "unsupported endianness"
+  n = (long) be64dec(sptr);
+#else /* 32bit */
+  n = I64_literal(be32dec(sptr), be32dec(sptr + 4));
 #endif
   return (value) caml_copy_int64(n);
-#else /* 32bit */
-  {
-    uint32_t *uisptr = (uint32_t *) sptr;
-    uint32_t upper = *uisptr++;
-    uint32_t lower = *uisptr;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-    n =
-      I64_or(
-        I64_lsl(I64_of_int32(bswap_32(upper)), 32),
-        I64_of_int32(bswap_32(lower)));
-#elif __BYTE_ORDER == __BIG_ENDIAN
-    n = I64_or(I64_lsl(I64_of_int32(upper), 32), I64_of_int32(lower));
-#else
-#error "unsupported endianness"
-#endif
-    return (value) caml_copy_int64(n);
-  }
-#endif
 }
 MK_ML_READER(network64_int64)

File base/bin-prot/lib/size.ml

 #endif
 
 #ifdef ARCH_SIXTYFOUR
-let max_int_int64 = Int64.of_int max_int
-let min_int_int64 = Int64.of_int min_int
 let bin_size_int64 n =
-  if n > max_int_int64 || n < min_int_int64 then 9
+  if n >= 0x80000000L || n < -0x80000000L then 9
   else bin_size_int (Int64.to_int n)
 #else
 let bin_size_int64 n =

File base/bin-prot/lib/size.mli

-(** compute size of values in the binary protocol. *)
+(** Compute size of values in the binary protocol. *)
 
 open Common
 

File base/bin-prot/lib/type_class.ml

     } \
   let bin_/**/NAME bin_el1 bin_el2 bin_el3 = \
     { \
-      writer = bin_writer_/**/NAME bin_el1.writer bin_el2.writer bin_el3.writer; \
-      reader = bin_reader_/**/NAME bin_el1.reader bin_el2.reader bin_el3.reader; \
+      writer = \
+        bin_writer_/**/NAME bin_el1.writer bin_el2.writer bin_el3.writer; \
+      reader = \
+        bin_reader_/**/NAME bin_el1.reader bin_el2.reader bin_el3.reader; \
     }
 
 MK_BASE1(ref)

File base/bin-prot/lib/type_class.mli

-(** sizers, writers, and readers in records *)
+(** Sizers, writers, and readers in records *)
 
 open Common
 

File base/bin-prot/lib/unsafe_common.mli

-(** functions common to unsafe binary protocol conversion. *)
+(** Functions common to unsafe binary protocol conversion. *)
 
-(** NOTE:these functions are not supposed to be called by the casual
+(** NOTE: these functions are not supposed to be called by the casual
     user.  They are required by automatically generated code, or if a
     developer really needs to get down and dirty for performance reasons.
 

File base/bin-prot/lib/unsafe_read_c.ml

   List.rev rev_lst
 
 #ifndef ARCH_SIXTYFOUR
-let dummy_float_buf = Array1.create char c_layout 8
+let dummy_float_buf = create_buf 8
 let () = ignore (Write_ml.bin_write_float dummy_float_buf ~pos:0 3.1)
 let dummy_float_buf_eptr = get_eptr dummy_float_buf ~pos:0
 let max_array_length_2 = Sys.max_array_length / 2

File base/bin-prot/lib/unsafe_read_c.mli

-(** reading values from the binary protocol using unsafe C. *)
+(** Reading values from the binary protocol using unsafe C. *)
 
 open Common
 open Unsafe_common

File base/bin-prot/lib/unsafe_write_c.mli

-(** writing values to the binary protocol using unsafe C. *)
+(** Writing values to the binary protocol using unsafe C. *)
 
 open Common
 open Unsafe_common

File base/bin-prot/lib/utils.mli

-(** utility functions for user convenience *)
+(** Utility functions for user convenience *)
 
 open Bigarray
 open Common

File base/bin-prot/lib/write_c.mli

-(** wrapping unsafe C-style writers to safe ML-style ones. *)
+(** Wrapping unsafe C-style writers to safe ML-style ones. *)
 
 open Common
 open Unsafe_common

File base/bin-prot/lib/write_ml.ml

 #ifdef ARCH_SIXTYFOUR
 let bin_write_int32 buf ~pos n = bin_write_int buf ~pos (Int32.to_int n)
 #else
-let max_int_int32 = Int32.of_int max_int
-let min_int_int32 = Int32.of_int min_int
 let bin_write_int32 buf ~pos n =
-  if n > max_int_int32 || n < min_int_int32 then
+  if n >= 0x00008000l || n < -0x00008000l then
     let next = pos + 5 in
     check_next buf next;
     buf.{pos} <- Char.unsafe_chr code_int32;
 #endif
 
 #ifdef ARCH_SIXTYFOUR
-let max_int_int64 = Int64.of_int max_int
-let min_int_int64 = Int64.of_int min_int
 let bin_write_int64 buf ~pos n =
-  if n > max_int_int64 || n < min_int_int64 then
+  if n >= 0x80000000L || n < -0x80000000L then
     let next = pos + 9 in
     check_next buf next;
     buf.{pos} <- Char.unsafe_chr code_int64;
   else bin_write_int buf ~pos (Int64.to_int n)
 #else
 let bin_write_int64 buf ~pos n =
-  if Size.bin_size_int64 n = 9 then
+  if n >= 0x80000000L || n < -0x80000000L then
     let next = pos + 9 in
     check_next buf next;
     buf.{pos} <- Char.unsafe_chr code_int64;

File base/bin-prot/lib/write_ml.mli

-(** writing values to the binary protocol using (mostly) OCaml. *)
+(** Writing values to the binary protocol using (mostly) OCaml. *)
 
 open Bigarray
 
 val bin_write_float_array : float array writer
 
 val bin_write_variant_tag : [> ] writer
-(** [bin_write_variant_tag] writes out the exact bit representation of
-    the variant tag of the given value (= 32 bits). *)
+(** [bin_write_variant_tag] writes out the exact little-endian bit
+    representation of the variant tag of the given value (= 32 bits). *)
 
 val bin_write_int_8bit : int writer
-(** [bin_write_int_8bit] writes out the exact bit representation of
-    the given [int] value using the lower 8 bits. *)
+(** [bin_write_int_8bit] writes out the exact little-endian bit representation
+    of the given [int] value using the lower 8 bits. *)
 
 val bin_write_int_16bit : int writer
-(** [bin_write_int_16bit] writes out the exact bit representation of
-    the given [int] value using the lower 16 bits. *)
+(** [bin_write_int_16bit] writes out the exact little-endian bit representation
+    of the given [int] value using the lower 16 bits. *)
 
 val bin_write_int_32bit : int writer
-(** [bin_write_int_32bit] writes out the exact bit representation of
-    the given [int] value using the lower 32 bits. *)
+(** [bin_write_int_32bit] writes out the exact little-endian bit representation
+    of the given [int] value using the lower 32 bits. *)
 
 val bin_write_int_64bit : int writer
-(** [bin_write_int_64bit] writes out the exact bit representation of
-    the given [int] value using all 64 bits. *)
+(** [bin_write_int_64bit] writes out the exact little-endian bit representation
+    of the given [int] value using all 64 bits.  On 32bit platforms negative
+    numbers will be sign-extended in the 64bit representation. *)
 
 val bin_write_int64_bits : int64 writer
-(** [bin_write_int64_bits] writes out the exact bit representation of
-    the given [int64] value. *)
+(** [bin_write_int64_bits] writes out the exact little-endian bit
+    representation of the given [int64] value. *)
 
 val bin_write_network16_int : int writer
 (** [bin_write_network16_int] writes out an integer in 16bit network

File base/bin-prot/lib/write_stubs.c

 static inline void do_write_int16(char *sptr, short n)
 {
   *sptr++ = CODE_INT16;
-  *(short *) sptr = n;
+  le16enc(sptr, n);
 }
 
 static inline value write_int16(char *sptr, char *eptr, short n)
 static inline void do_write_int32(char *sptr, int n)
 {
   *sptr++ = CODE_INT32;
-  *(int *) sptr = n;
+  le32enc(sptr, n);
 }
 
 static inline value write_int32(char *sptr, char *eptr, int n)
 static inline void do_write_int64(char *sptr, long n)
 {
   *sptr++ = CODE_INT64;
-  *(long *) sptr = n;
+  le64enc(sptr, n);
 }
 
 static inline value write_int64(char *sptr, char *eptr, long n)
 
 /* Writing 64bit integers */
 
-#ifdef ARCH_INT64_TYPE
-#include "int64_native.h"
-#else
-#include "int64_emul.h"
-#endif
-
 #ifndef ARCH_SIXTYFOUR
 static inline value write_int64_type(char *sptr, char *eptr, int64 n)
 {
   char *next = sptr + 9;
-  int *isptr;
+  int32 lower, upper;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
   *sptr++ = CODE_INT64;
-  isptr = (int *) sptr;
-  *isptr++ = I64_to_int32(n);
-  *isptr = I64_to_int32(I64_lsr(n, 32));
+  I64_split(n, upper, lower);
+  le32enc(sptr, lower);
+  le32enc(sptr + 4, upper);
   return (value) next;
 }
 
 CAMLprim inline value write_float_stub(char *sptr, char *eptr, value v_n)
 {
   char *next = sptr + sizeof(double);
+  double n = Double_val(v_n);
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  *(double *) sptr = Double_val(v_n);
+  memcpy(sptr, &n, sizeof(double));
   return (value) next;
 }
 
 
 /* Writing polymorphic variants */
 
-CAMLprim inline value write_variant_tag_stub(char *sptr, char *eptr, value v)
+CAMLprim inline value write_variant_tag_stub(
+  char *sptr, char *eptr, value v_tag)
 {
   char *next = sptr + 4;
+  int tag;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  *(int *) sptr = (int) (Is_block(v) ? Field(v, 0) : v);
+  tag = (int) (Is_block(v_tag) ? Field(v_tag, 0) : v_tag);
+  le32enc(sptr, tag);
   return (value) next;
 }
 
 {
   char *next = sptr + 2;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  *(short *) sptr = (short) Int_val(v_n);
+  le16enc(sptr, Int_val(v_n));
   return (value) next;
 }
 MK_ML_WRITER(int_16bit)
 {
   char *next = sptr + 4;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  *(int *) sptr = Int_val(v_n);
+  le32enc(sptr, Int_val(v_n));
   return (value) next;
 }
 MK_ML_WRITER(int_32bit)
 
 CAMLprim value write_int_64bit_stub(char *sptr, char *eptr, value v_n)
 {
-  long n = Long_val(v_n);
   char *next = sptr + 8;
-  long *lsptr = (long *) sptr;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  *lsptr = n;
-#ifndef ARCH_SIXTYFOUR
-  *++lsptr = (n < 0) ? 0xFFFFFFFFl : 0l;
+#ifdef ARCH_SIXTYFOUR
+  le64enc(sptr, Long_val(v_n));
+#else
+  {
+    long n = Long_val(v_n);
+    long tmp = (n < 0) ? 0xFFFFFFFFl : 0l;
+    le32enc(sptr, n);
+    memcpy(sptr + 4, &tmp, sizeof(long));
+  }
 #endif
   return (value) next;
 }
   char *next = sptr + 8;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 #ifdef ARCH_SIXTYFOUR
-  *(long *) sptr = Int64_val(v_n);
+  le64enc(sptr, Int64_val(v_n));
 #else
   {
     int64 n = Int64_val(v_n);
-    unsigned int *uisptr = (unsigned int *) sptr;
-    *uisptr = I64_to_int32(n);
-    uisptr++;
-    *uisptr = I64_to_int32(I64_lsr(n, 32));
+    unsigned int lower, upper;
+    I64_split(n, upper, lower);
+    le32enc(sptr, lower);
+    le32enc(sptr + 4, upper);
   }
 #endif
   return (value) next;
 {
   char *next = sptr + 2;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  *((uint16_t *) sptr) = (uint16_t) htons(Int_val(v_n));
+  be16enc(sptr, Int_val(v_n));
   return (value) next;
 }
 MK_ML_WRITER(network16_int)
 {
   char *next = sptr + 4;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  *((uint32_t *) sptr) = (uint32_t) htonl(Int_val(v_n));
+  be32enc(sptr, Int_val(v_n));
   return (value) next;
 }
 MK_ML_WRITER(network32_int)
 {
   char *next = sptr + 4;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
-  *((uint32_t *) sptr) = htonl(Int32_val(v_n));
+  be32enc(sptr, Int32_val(v_n));
   return (value) next;
 }
 MK_ML_WRITER(network32_int32)
   char *sptr, char *eptr, value v_n)
 {
   char *next = sptr + 8;
-  long n = Long_val(v_n);
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 #ifdef ARCH_SIXTYFOUR
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  *((uint64_t *) sptr) = bswap_64(n);
-#elif __BYTE_ORDER == __BIG_ENDIAN
-  *((uint64_t *) sptr) = n;
-#else
-#error "unsupported endianness"
-#endif
+  be64enc(sptr, Long_val(v_n));
 #else /* 32bit */
-  *((unsigned int *) sptr) = 0;
-  sptr += 4;
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  *((unsigned int *) sptr) = bswap_32((unsigned int) n);
-#else
-  *((unsigned int *) sptr) = (unsigned int) n;
-#endif
+  {
+    unsigned int tmp = 0;
+    memcpy(sptr, &tmp, 4);
+    be32enc(sptr + 4, Long_val(v_n));
+  }
 #endif
   return (value) next;
 }
   char *next = sptr + 8;
   if (unlikely(next > eptr)) caml_raise_constant(*v_bin_prot_exc_Buffer_short);
 #ifdef ARCH_SIXTYFOUR
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-  *((uint64_t *) sptr) = bswap_64(Int64_val(v_n));
-#elif __BYTE_ORDER == __BIG_ENDIAN
-  *((uint64_t *) sptr) = Int64_val(v_n);
-#else
-#error "unsupported endianness"
-#endif
-#else
-#if __BYTE_ORDER == __LITTLE_ENDIAN
+  be64enc(sptr, Int64_val(v_n));
+#else /* 32bit */
   {
     int64 n = Int64_val(v_n);
-    uint32_t *uisptr = (uint32_t *) sptr;
-    *uisptr = bswap_32(I64_to_int32(I64_lsr(n, 32)));
-    uisptr++;
-    *uisptr = bswap_32(I64_to_int32(n));
+    uint32_t lower, upper;
+    I64_split(n, upper, lower);
+    be32enc(sptr, upper);
+    be32enc(sptr + 4, lower);
   }
-#elif __BYTE_ORDER == __BIG_ENDIAN
-  {
-    int64 n = Int64_val(v_n);
-    uint32_t *uisptr = (uint32_t *) sptr;
-    *uisptr = I64_to_int32(I64_lsr(n, 32));
-    uisptr++;
-    *uisptr = I64_to_int32(n);
-  }
-#else
-#error "unsupported endianness"
-#endif
 #endif
   return (value) next;
 }

File base/bin-prot/oasis.sh

 OASISFormat:  0.2
 OCamlVersion: >= 3.12
 Name:         bin_prot
-Version:      1.3.2
+Version:      2.0.7
 Synopsis:     binary protocol generator
 Authors:      Markus Mottl,
-              Jane street capital
-Copyrights:   (C) 2008-2011 Jane Street Capital LLC
+              Jane Street Holding LLC
+Copyrights:   (C) 2008-2011 Jane Street Holding LLC
 License:      LGPL-2.1 with OCaml linking exception
 LicenseFile:  LICENSE
 Plugins:      StdFiles (0.2),
               DevFiles (0.2),
               META (0.2)
-BuildTools:   ocamlbuild
+BuildTools:   ocamlbuild, camlp4o
 Description:  binary protocol generator
 XStdFilesAUTHORS: false
 XStdFilesINSTALLFilename: INSTALL
   CSources:           common_stubs.c,
                       common_stubs.h,
                       int64_native.h,
+                      int64_emul.h,
                       write_stubs.c,
                       read_stubs.c
   BuildDepends:       unix,bigarray
 
-
 Library pa_bin_prot
   Path:               syntax
   FindlibName:        syntax
   FindlibParent:      bin_prot
-  modules:            Pa_bin_prot
-  BuildDepends:       camlp4,camlp4.lib,camlp4.quotations,type-conv (>= 2.0.1)
+  Modules:            Pa_bin_prot
+  BuildDepends:       camlp4.quotations,camlp4.extend,type-conv (>= 3.0.4)
+  CompiledObject:     byte
   XMETAType:          syntax
-  XMETARequires:      type-conv
+  XMETARequires:      type-conv,bin_prot
   XMETADescription:   Syntax extension for binary protocol generator
 
 Flag tests
 <syntax/pa_bin_prot.ml>: syntax_camlp4o
 EOF
 
+make_myocamlbuild $HERE/myocamlbuild.ml <<EOF
+(* We probably will want to set this up in the \`configure\` script at some
+   point.*)
+let is_darwin =
+  Ocamlbuild_pack.My_unix.run_and_open "uname -s" input_line = "Darwin"
+
+let cpp =
+  let base_cpp = "cpp -traditional -undef -w" in
+  match Sys.word_size with
+  | 64 -> S [A "-pp"; P (base_cpp ^ " -DARCH_SIXTYFOUR")]
+  | 32 -> S [A "-pp"; P base_cpp]
+  | _ -> assert false
+;;
+
+Ocamlbuild_plugin.dispatch
+  begin
+    function
+      | After_rules as e ->
+          dep ["ocaml"; "ocamldep"; "mlh"] ["lib/int_codes.mlh"];
+
+          flag ["ocamldep"; "ocaml"; "use_pa_bin_prot"]
+            (S [A "-ppopt"; P"syntax/pa_bin_prot.cma"]);
+
+          flag ["compile"; "ocaml"; "use_pa_bin_prot"]
+            (S [A "-ppopt"; P "syntax/pa_bin_prot.cma"]);
+
+          flag ["ocamldep"; "ocaml"; "cpp"] cpp;
+
+          flag ["compile"; "ocaml"; "cpp"] cpp;
+
+          let cflags =
+            let flags =
+              [
+                "-pipe";
+                "-g";
+                "-fPIC";
+                "-O2";
+                "-fomit-frame-pointer";
+                "-fsigned-char";
+                "-Wall";
+                "-pedantic";
+                "-Wextra";
+                "-Wunused";
+                "-Werror";
+                "-Wno-long-long";
+              ]
+            in
+            let flags = if is_darwin then "-DOS_DARWIN" :: flags else flags in
+            let f flag = [A "-ccopt"; A flag] in
+            List.concat (List.map f flags)
+          in
+          flag ["compile"; "c"] (S cflags);
+          dispatch_default e
+      | e -> dispatch_default e
+  end
+;;
+EOF
+
 cd $HERE
 oasis setup
 enable_pack_in_setup_ml bin_prot
 
 ./configure "$@"
-

File base/bin-prot/syntax/pa_bin_prot.ml

     | <:ctyp< $tp1$ $tp2$ >> ->
         `Fun (bin_size_appl_fun full_type_name _loc tp1 tp2)
     | <:ctyp< ( $tup:tp$ ) >> -> bin_size_tuple full_type_name _loc tp
-    | <:ctyp< '$parm$ >> -> `Fun (Gen.ide _loc ("_size_of_" ^ parm))
+    | <:ctyp< '$parm$ >> -> `Fun <:expr< $lid:"_size_of_" ^ parm$ >>
     | <:ctyp< $id:id$ >> -> `Fun (bin_size_path_fun _loc id)
     | <:ctyp< $_$ -> $_$ >> ->
         failwith
   and bin_size_tuple full_type_name _loc tp =
     let cnv_patts patts = <:patt< ( $tup:paCom_of_list patts$ ) >> in
     let get_tp tp = tp in
-    let mk_patt _loc v_name _ = Gen.idp _loc v_name in
+    let mk_patt _loc v_name _ = <:patt< $lid:v_name$ >> in
     bin_size_tup_rec full_type_name _loc cnv_patts get_tp mk_patt tp
 
   (* Conversion of records *)
     let bindings =
       let mk_binding parm =
         <:binding<
-          $Gen.idp _loc ("_size_of_" ^ parm)$ = fun _v ->
+          $lid:"_size_of_" ^ parm$ = fun _v ->
             raise (Bin_prot.Common.Poly_rec_write $str:full_type_name$)
         >>
       in
       | <:ctyp< $uid:_$ >> -> has_atoms := true; <:match_case< >>
       | <:ctyp< $uid:cnstr$ of $tp$ >> ->
           let get_tp tp = tp in
-          let mk_patt _loc v_name _ = Gen.idp _loc v_name in
+          let mk_patt _loc v_name _ = <:patt< $lid:v_name$ >> in
           let patts, size_args =
             bin_size_args full_type_name _loc get_tp mk_patt tp
           in
       | `Match matchings -> <:expr< fun [ $matchings$ ] >>
     in
     let tparam_cnvs = List.map ((^) "_size_of_" *** Gen.get_tparam_id) tps in
-    let tparam_patts = List.map (Gen.idp _loc) tparam_cnvs in
+    let mk_pat id = <:patt< $lid:id$ >> in
+    let tparam_patts = List.map mk_pat tparam_cnvs in
     <:binding<
       $lid:"bin_size_" ^ type_name$ = $Gen.abstract _loc tparam_patts body$
     >>
     | <:ctyp< $tp1$ $tp2$ >> ->
         `Fun (bin_write_appl_fun full_type_name _loc tp1 tp2)
     | <:ctyp< ( $tup:tp$ ) >> -> bin_write_tuple full_type_name _loc tp
-    | <:ctyp< '$parm$ >> -> `Fun (Gen.ide _loc ("_write_" ^ parm))
+    | <:ctyp< '$parm$ >> -> `Fun <:expr< $lid:"_write_" ^ parm$ >>
     | <:ctyp< $id:id$ >> -> `Fun (bin_write_path_fun _loc id)
     | <:ctyp< $_$ -> $_$ >> ->
         failwith
   and