removed CRs
diff --git a/binfiles/z32.elf b/binfiles/z32.elf
new file mode 100755
index 0000000..d6b3cd1
--- /dev/null
+++ b/binfiles/z32.elf
Binary files differ
diff --git a/elftools/common/exceptions.py b/elftools/common/exceptions.py
index a4df582..8a40877 100644
--- a/elftools/common/exceptions.py
+++ b/elftools/common/exceptions.py
@@ -1,14 +1,14 @@
-#-------------------------------------------------------------------------------

-# elftools: common/exceptions.py

-#

-# Exception classes for elftools

-#

-# Eli Bendersky (eliben@gmail.com)

-# This code is in the public domain

-#-------------------------------------------------------------------------------

-class ELFError(Exception): 

+#-------------------------------------------------------------------------------
+# elftools: common/exceptions.py
+#
+# Exception classes for elftools
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+class ELFError(Exception): 
     pass
-

-class ELFParseError(ELFError):

-    pass

-

+
+class ELFParseError(ELFError):
+    pass
+
diff --git a/elftools/common/utils.py b/elftools/common/utils.py
index 230ba96..666176f 100644
--- a/elftools/common/utils.py
+++ b/elftools/common/utils.py
@@ -1,32 +1,32 @@
-#-------------------------------------------------------------------------------

-# elftools: common/utils.py

-#

-# Miscellaneous utilities for elftools

-#

-# Eli Bendersky (eliben@gmail.com)

-# This code is in the public domain

-#-------------------------------------------------------------------------------

-from .exceptions import ELFParseError, ELFError

-

-

-def struct_parse(struct, stream, stream_pos=None):

-    """ Convenience function for using the given struct to parse a stream (at

-        its current location).

-        If stream_pos is provided, the stream is seeked to this position before

-        the parsing is done.

-        Wraps the error thrown by construct with our own error.

-    """

-    try:

-        if stream_pos is not None:

-            stream.seek(stream_pos)

-        return struct.parse_stream(stream)

-    except ConstructError as e:

-        raise ELFParseError(e.message)

-    

-

+#-------------------------------------------------------------------------------
+# elftools: common/utils.py
+#
+# Miscellaneous utilities for elftools
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+from .exceptions import ELFParseError, ELFError
+
+
+def struct_parse(struct, stream, stream_pos=None):
+    """ Convenience function for using the given struct to parse a stream (at
+        its current location).
+        If stream_pos is provided, the stream is seeked to this position before
+        the parsing is done.
+        Wraps the error thrown by construct with our own error.
+    """
+    try:
+        if stream_pos is not None:
+            stream.seek(stream_pos)
+        return struct.parse_stream(stream)
+    except ConstructError as e:
+        raise ELFParseError(e.message)
+    
+
 def elf_assert(cond, msg=''):
-    """ Assert that cond is True, otherwise raise ELFError(msg)

-    """

-    if not cond:

-        raise ELFError(msg)

-

+    """ Assert that cond is True, otherwise raise ELFError(msg)
+    """
+    if not cond:
+        raise ELFError(msg)
+
diff --git a/elftools/construct/__init__.py b/elftools/construct/__init__.py
index 0b97feb..4814bcc 100644
--- a/elftools/construct/__init__.py
+++ b/elftools/construct/__init__.py
@@ -1,81 +1,81 @@
-"""

-Construct 2.00 -- parsing made even more fun (and faster)

-

-Homepage:

-http://construct.wikispaces.com

-

-Typical usage:

->>> from construct import *

-

-Example:

->>> from construct import *

->>>

->>> s = Struct("foo",

-...     UBInt8("a"),

-...     UBInt16("b"),

-... )

->>>

->>> s.parse("\x01\x02\x03")

-Container(a = 1, b = 515)

->>> print s.parse("\x01\x02\x03")

-Container:

-    a = 1

-    b = 515

->>> s.build(Container(a = 1, b = 0x0203))

-"\x01\x02\x03"

-"""

-from core import *

-from adapters import *

-from macros import *

-from debug import Probe, Debugger

-

-

-#===============================================================================

-# meta data

-#===============================================================================

-__author__ = "tomer filiba (tomerfiliba [at] gmail.com)"

-__version__ = "2.00"

-

-#===============================================================================

-# shorthands

-#===============================================================================

-Bits = BitField

-Byte = UBInt8

-Bytes = Field

-Const = ConstAdapter

-Tunnel = TunnelAdapter

-Embed = Embedded

-

-#===============================================================================

-# backward compatibility with RC1

-#===============================================================================

-MetaField = Field

-MetaBytes = Field

-GreedyRepeater = GreedyRange

-OptionalGreedyRepeater = OptionalGreedyRange

-Repeater = Array

-StrictRepeater = Array

-MetaRepeater = Array

-OneOfValidator = OneOf

-NoneOfValidator = NoneOf

-

-#===============================================================================

-# don't want to leek these out...

-#===============================================================================

-del encode_bin, decode_bin, int_to_bin, bin_to_int, swap_bytes

-del Packer, StringIO

-del HexString, LazyContainer, AttrDict

-

-

-

-

-

-

-

-

-

-

-

-

-

-

+"""
+Construct 2.00 -- parsing made even more fun (and faster)
+
+Homepage:
+http://construct.wikispaces.com
+
+Typical usage:
+>>> from construct import *
+
+Example:
+>>> from construct import *
+>>>
+>>> s = Struct("foo",
+...     UBInt8("a"),
+...     UBInt16("b"),
+... )
+>>>
+>>> s.parse("\x01\x02\x03")
+Container(a = 1, b = 515)
+>>> print s.parse("\x01\x02\x03")
+Container:
+    a = 1
+    b = 515
+>>> s.build(Container(a = 1, b = 0x0203))
+"\x01\x02\x03"
+"""
+from core import *
+from adapters import *
+from macros import *
+from debug import Probe, Debugger
+
+
+#===============================================================================
+# meta data
+#===============================================================================
+__author__ = "tomer filiba (tomerfiliba [at] gmail.com)"
+__version__ = "2.00"
+
+#===============================================================================
+# shorthands
+#===============================================================================
+Bits = BitField
+Byte = UBInt8
+Bytes = Field
+Const = ConstAdapter
+Tunnel = TunnelAdapter
+Embed = Embedded
+
+#===============================================================================
+# backward compatibility with RC1
+#===============================================================================
+MetaField = Field
+MetaBytes = Field
+GreedyRepeater = GreedyRange
+OptionalGreedyRepeater = OptionalGreedyRange
+Repeater = Array
+StrictRepeater = Array
+MetaRepeater = Array
+OneOfValidator = OneOf
+NoneOfValidator = NoneOf
+
+#===============================================================================
+# don't want to leek these out...
+#===============================================================================
+del encode_bin, decode_bin, int_to_bin, bin_to_int, swap_bytes
+del Packer, StringIO
+del HexString, LazyContainer, AttrDict
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/elftools/construct/adapters.py b/elftools/construct/adapters.py
index 69c84d9..182e108 100644
--- a/elftools/construct/adapters.py
+++ b/elftools/construct/adapters.py
@@ -1,484 +1,484 @@
-from core import Adapter, AdaptationError, Pass

-from lib import int_to_bin, bin_to_int, swap_bytes, StringIO

-from lib import FlagsContainer, HexString

-

-

-#===============================================================================

-# exceptions

-#===============================================================================

-class BitIntegerError(AdaptationError):

-    __slots__ = []

-class MappingError(AdaptationError):

-    __slots__ = []

-class ConstError(AdaptationError):

-    __slots__ = []

-class ValidationError(AdaptationError):

-    __slots__ = []

-class PaddingError(AdaptationError):

-    __slots__ = []

-

-#===============================================================================

-# adapters

-#===============================================================================

-class BitIntegerAdapter(Adapter):

-    """

-    Adapter for bit-integers (converts bitstrings to integers, and vice versa).

-    See BitField.

-    

-    Parameters:

-    * subcon - the subcon to adapt

-    * width - the size of the subcon, in bits

-    * swapped - whether to swap byte order (little endian/big endian). 

-      default is False (big endian)

-    * signed - whether the value is signed (two's complement). the default

-      is False (unsigned)

-    * bytesize - number of bits per byte, used for byte-swapping (if swapped).

-      default is 8.

-    """

-    __slots__ = ["width", "swapped", "signed", "bytesize"]

-    def __init__(self, subcon, width, swapped = False, signed = False, 

-                 bytesize = 8):

-        Adapter.__init__(self, subcon)

-        self.width = width

-        self.swapped = swapped

-        self.signed = signed

-        self.bytesize = bytesize

-    def _encode(self, obj, context):

-        if obj < 0 and not self.signed:

-            raise BitIntegerError("object is negative, but field is not signed",

-                obj)

-        obj2 = int_to_bin(obj, width = self.width)

-        if self.swapped:

-            obj2 = swap_bytes(obj2, bytesize = self.bytesize)

-        return obj2

-    def _decode(self, obj, context):

-        if self.swapped:

-            obj = swap_bytes(obj, bytesize = self.bytesize)

-        return bin_to_int(obj, signed = self.signed)

-

-class MappingAdapter(Adapter):

-    """

-    Adapter that maps objects to other objects.

-    See SymmetricMapping and Enum.

-    

-    Parameters:

-    * subcon - the subcon to map

-    * decoding - the decoding (parsing) mapping (a dict)

-    * encoding - the encoding (building) mapping (a dict)

-    * decdefault - the default return value when the object is not found

-      in the decoding mapping. if no object is given, an exception is raised.

-      if `Pass` is used, the unmapped object will be passed as-is

-    * encdefault - the default return value when the object is not found

-      in the encoding mapping. if no object is given, an exception is raised.

-      if `Pass` is used, the unmapped object will be passed as-is

-    """

-    __slots__ = ["encoding", "decoding", "encdefault", "decdefault"]

-    def __init__(self, subcon, decoding, encoding, 

-                 decdefault = NotImplemented, encdefault = NotImplemented):

-        Adapter.__init__(self, subcon)

-        self.decoding = decoding

-        self.encoding = encoding

-        self.decdefault = decdefault

-        self.encdefault = encdefault

-    def _encode(self, obj, context):

-        try:

-            return self.encoding[obj]

-        except (KeyError, TypeError):

-            if self.encdefault is NotImplemented:

-                raise MappingError("no encoding mapping for %r [%s]" % (

-                    obj, self.subcon.name))

-            if self.encdefault is Pass:

-                return obj

-            return self.encdefault

-    def _decode(self, obj, context):

-        try:

-            return self.decoding[obj]

-        except (KeyError, TypeError):

-            if self.decdefault is NotImplemented:

-                raise MappingError("no decoding mapping for %r [%s]"  % (

-                    obj, self.subcon.name))

-            if self.decdefault is Pass:

-                return obj

-            return self.decdefault

-

-class FlagsAdapter(Adapter):

-    """

-    Adapter for flag fields. Each flag is extracted from the number, resulting

-    in a FlagsContainer object. Not intended for direct usage.

-    See FlagsEnum.

-    

-    Parameters

-    * subcon - the subcon to extract

-    * flags - a dictionary mapping flag-names to their value

-    """

-    __slots__ = ["flags"]

-    def __init__(self, subcon, flags):

-        Adapter.__init__(self, subcon)

-        self.flags = flags

-    def _encode(self, obj, context):

-        flags = 0

-        for name, value in self.flags.iteritems():

-            if getattr(obj, name, False):

-                flags |= value

-        return flags

-    def _decode(self, obj, context):

-        obj2 = FlagsContainer()

-        for name, value in self.flags.iteritems():

-            setattr(obj2, name, bool(obj & value))

-        return obj2

-

-class StringAdapter(Adapter):

-    """

-    Adapter for strings. Converts a sequence of characters into a python 

-    string, and optionally handles character encoding.

-    See String.

-    

-    Parameters:

-    * subcon - the subcon to convert

-    * encoding - the character encoding name (e.g., "utf8"), or None to 

-      return raw bytes (usually 8-bit ASCII).

-    """

-    __slots__ = ["encoding"]

-    def __init__(self, subcon, encoding = None):

-        Adapter.__init__(self, subcon)

-        self.encoding = encoding

-    def _encode(self, obj, context):

-        if self.encoding:

-            obj = obj.encode(self.encoding)

-        return obj

-    def _decode(self, obj, context):

-        obj = "".join(obj)

-        if self.encoding:

-            obj = obj.decode(self.encoding)

-        return obj

-

-class PaddedStringAdapter(Adapter):

-    r"""

-    Adapter for padded strings.

-    See String.

-    

-    Parameters:

-    * subcon - the subcon to adapt

-    * padchar - the padding character. default is "\x00".

-    * paddir - the direction where padding is placed ("right", "left", or 

-      "center"). the default is "right". 

-    * trimdir - the direction where trimming will take place ("right" or 

-      "left"). the default is "right". trimming is only meaningful for

-      building, when the given string is too long. 

-    """

-    __slots__ = ["padchar", "paddir", "trimdir"]

-    def __init__(self, subcon, padchar = "\x00", paddir = "right", 

-                 trimdir = "right"):

-        if paddir not in ("right", "left", "center"):

-            raise ValueError("paddir must be 'right', 'left' or 'center'", 

-                paddir)

-        if trimdir not in ("right", "left"):

-            raise ValueError("trimdir must be 'right' or 'left'", trimdir)

-        Adapter.__init__(self, subcon)

-        self.padchar = padchar

-        self.paddir = paddir

-        self.trimdir = trimdir

-    def _decode(self, obj, context):

-        if self.paddir == "right":

-            obj = obj.rstrip(self.padchar)

-        elif self.paddir == "left":

-            obj = obj.lstrip(self.padchar)

-        else:

-            obj = obj.strip(self.padchar)

-        return obj

-    def _encode(self, obj, context):

-        size = self._sizeof(context)

-        if self.paddir == "right":

-            obj = obj.ljust(size, self.padchar)

-        elif self.paddir == "left":

-            obj = obj.rjust(size, self.padchar)

-        else:

-            obj = obj.center(size, self.padchar)

-        if len(obj) > size:

-            if self.trimdir == "right":

-                obj = obj[:size]

-            else:

-                obj = obj[-size:]

-        return obj

-

-class LengthValueAdapter(Adapter):

-    """

-    Adapter for length-value pairs. It extracts only the value from the 

-    pair, and calculates the length based on the value.

-    See PrefixedArray and PascalString.

-    

-    Parameters:

-    * subcon - the subcon returning a length-value pair

-    """

-    __slots__ = []

-    def _encode(self, obj, context):

-        return (len(obj), obj)

-    def _decode(self, obj, context):

-        return obj[1]

-

-class CStringAdapter(StringAdapter):

-    r"""

-    Adapter for C-style strings (strings terminated by a terminator char).

-    

-    Parameters:

-    * subcon - the subcon to convert

-    * terminators - a sequence of terminator chars. default is "\x00".

-    * encoding - the character encoding to use (e.g., "utf8"), or None to

-      return raw-bytes. the terminator characters are not affected by the 

-      encoding.

-    """

-    __slots__ = ["terminators"]

-    def __init__(self, subcon, terminators = "\x00", encoding = None):

-        StringAdapter.__init__(self, subcon, encoding = encoding)

-        self.terminators = terminators

-    def _encode(self, obj, context):

-        return StringAdapter._encode(self, obj, context) + self.terminators[0]

-    def _decode(self, obj, context):

-        return StringAdapter._decode(self, obj[:-1], context)

-

-class TunnelAdapter(Adapter):

-    """

-    Adapter for tunneling (as in protocol tunneling). A tunnel is construct

-    nested upon another (layering). For parsing, the lower layer first parses

-    the data (note: it must return a string!), then the upper layer is called

-    to parse that data (bottom-up). For building it works in a top-down manner;

-    first the upper layer builds the data, then the lower layer takes it and

-    writes it to the stream.

-    

-    Parameters:

-    * subcon - the lower layer subcon

-    * inner_subcon - the upper layer (tunneled/nested) subcon

-    

-    Example:

-    # a pascal string containing compressed data (zlib encoding), so first

-    # the string is read, decompressed, and finally re-parsed as an array

-    # of UBInt16

-    TunnelAdapter(

-        PascalString("data", encoding = "zlib"),

-        GreedyRange(UBInt16("elements"))

-    )

-    """

-    __slots__ = ["inner_subcon"]

-    def __init__(self, subcon, inner_subcon):

-        Adapter.__init__(self, subcon)

-        self.inner_subcon = inner_subcon

-    def _decode(self, obj, context):

-        return self.inner_subcon._parse(StringIO(obj), context)

-    def _encode(self, obj, context):

-        stream = StringIO()

-        self.inner_subcon._build(obj, stream, context)

-        return stream.getvalue()

-

-class ExprAdapter(Adapter):

-    """

-    A generic adapter that accepts 'encoder' and 'decoder' as parameters. You

-    can use ExprAdapter instead of writing a full-blown class when only a 

-    simple expression is needed.

-    

-    Parameters:

-    * subcon - the subcon to adapt

-    * encoder - a function that takes (obj, context) and returns an encoded 

-      version of obj

-    * decoder - a function that takes (obj, context) and returns an decoded 

-      version of obj

-    

-    Example:

-    ExprAdapter(UBInt8("foo"), 

-        encoder = lambda obj, ctx: obj / 4,

-        decoder = lambda obj, ctx: obj * 4,

-    )

-    """

-    __slots__ = ["_encode", "_decode"]

-    def __init__(self, subcon, encoder, decoder):

-        Adapter.__init__(self, subcon)

-        self._encode = encoder

-        self._decode = decoder

-

-class HexDumpAdapter(Adapter):

-    """

-    Adapter for hex-dumping strings. It returns a HexString, which is a string

-    """

-    __slots__ = ["linesize"]

-    def __init__(self, subcon, linesize = 16):

-        Adapter.__init__(self, subcon)

-        self.linesize = linesize

-    def _encode(self, obj, context):

-        return obj

-    def _decode(self, obj, context):

-        return HexString(obj, linesize = self.linesize)

-

-class ConstAdapter(Adapter):

-    """

-    Adapter for enforcing a constant value ("magic numbers"). When decoding,

-    the return value is checked; when building, the value is substituted in.

-    

-    Parameters:

-    * subcon - the subcon to validate

-    * value - the expected value

-    

-    Example:

-    Const(Field("signature", 2), "MZ")

-    """

-    __slots__ = ["value"]

-    def __init__(self, subcon, value):

-        Adapter.__init__(self, subcon)

-        self.value = value

-    def _encode(self, obj, context):

-        if obj is None or obj == self.value:

-            return self.value

-        else:

-            raise ConstError("expected %r, found %r" % (self.value, obj))

-    def _decode(self, obj, context):

-        if obj != self.value:

-            raise ConstError("expected %r, found %r" % (self.value, obj))

-        return obj

-

-class SlicingAdapter(Adapter):

-    """

-    Adapter for slicing a list (getting a slice from that list)

-    

-    Parameters:

-    * subcon - the subcon to slice

-    * start - start index

-    * stop - stop index (or None for up-to-end)

-    * step - step (or None for every element)

-    """

-    __slots__ = ["start", "stop", "step"]

-    def __init__(self, subcon, start, stop = None):

-        Adapter.__init__(self, subcon)

-        self.start = start

-        self.stop = stop

-    def _encode(self, obj, context):

-        if self.start is None:

-            return obj

-        return [None] * self.start + obj

-    def _decode(self, obj, context):

-        return obj[self.start:self.stop]

-

-class IndexingAdapter(Adapter):

-    """

-    Adapter for indexing a list (getting a single item from that list)

-    

-    Parameters:

-    * subcon - the subcon to index

-    * index - the index of the list to get

-    """

-    __slots__ = ["index"]

-    def __init__(self, subcon, index):

-        Adapter.__init__(self, subcon)

-        if type(index) is not int:

-            raise TypeError("index must be an integer", type(index))

-        self.index = index

-    def _encode(self, obj, context):

-        return [None] * self.index + [obj]

-    def _decode(self, obj, context):

-        return obj[self.index]

-

-class PaddingAdapter(Adapter):

-    r"""

-    Adapter for padding.

-    

-    Parameters:

-    * subcon - the subcon to pad

-    * pattern - the padding pattern (character). default is "\x00")

-    * strict - whether or not to verify, during parsing, that the given 

-      padding matches the padding pattern. default is False (unstrict)

-    """

-    __slots__ = ["pattern", "strict"]

-    def __init__(self, subcon, pattern = "\x00", strict = False):

-        Adapter.__init__(self, subcon)

-        self.pattern = pattern

-        self.strict = strict

-    def _encode(self, obj, context):

-        return self._sizeof(context) * self.pattern

-    def _decode(self, obj, context):

-        if self.strict:

-            expected = self._sizeof(context) * self.pattern

-            if obj != expected:

-                raise PaddingError("expected %r, found %r" % (expected, obj))

-        return obj

-

-

-#===============================================================================

-# validators

-#===============================================================================

-class Validator(Adapter):

-    """

-    Abstract class: validates a condition on the encoded/decoded object. 

-    Override _validate(obj, context) in deriving classes.

-    

-    Parameters:

-    * subcon - the subcon to validate

-    """

-    __slots__ = []

-    def _decode(self, obj, context):

-        if not self._validate(obj, context):

-            raise ValidationError("invalid object", obj)

-        return obj

-    def _encode(self, obj, context):

-        return self._decode(obj, context)

-    def _validate(self, obj, context):

-        raise NotImplementedError()

-

-class OneOf(Validator):

-    """

-    Validates that the value is one of the listed values

-    

-    Parameters:

-    * subcon - the subcon to validate

-    * valids - a set of valid values

-    """

-    __slots__ = ["valids"]

-    def __init__(self, subcon, valids):

-        Validator.__init__(self, subcon)

-        self.valids = valids

-    def _validate(self, obj, context):

-        return obj in self.valids

-

-class NoneOf(Validator):

-    """

-    Validates that the value is none of the listed values

-    

-    Parameters:

-    * subcon - the subcon to validate

-    * invalids - a set of invalid values

-    """

-    __slots__ = ["invalids"]

-    def __init__(self, subcon, invalids):

-        Validator.__init__(self, subcon)

-        self.invalids = invalids

-    def _validate(self, obj, context):

-        return obj not in self.invalids

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

+from core import Adapter, AdaptationError, Pass
+from lib import int_to_bin, bin_to_int, swap_bytes, StringIO
+from lib import FlagsContainer, HexString
+
+
+#===============================================================================
+# exceptions
+#===============================================================================
+class BitIntegerError(AdaptationError):
+    __slots__ = []
+class MappingError(AdaptationError):
+    __slots__ = []
+class ConstError(AdaptationError):
+    __slots__ = []
+class ValidationError(AdaptationError):
+    __slots__ = []
+class PaddingError(AdaptationError):
+    __slots__ = []
+
+#===============================================================================
+# adapters
+#===============================================================================
+class BitIntegerAdapter(Adapter):
+    """
+    Adapter for bit-integers (converts bitstrings to integers, and vice versa).
+    See BitField.
+    
+    Parameters:
+    * subcon - the subcon to adapt
+    * width - the size of the subcon, in bits
+    * swapped - whether to swap byte order (little endian/big endian). 
+      default is False (big endian)
+    * signed - whether the value is signed (two's complement). the default
+      is False (unsigned)
+    * bytesize - number of bits per byte, used for byte-swapping (if swapped).
+      default is 8.
+    """
+    __slots__ = ["width", "swapped", "signed", "bytesize"]
+    def __init__(self, subcon, width, swapped = False, signed = False, 
+                 bytesize = 8):
+        Adapter.__init__(self, subcon)
+        self.width = width
+        self.swapped = swapped
+        self.signed = signed
+        self.bytesize = bytesize
+    def _encode(self, obj, context):
+        if obj < 0 and not self.signed:
+            raise BitIntegerError("object is negative, but field is not signed",
+                obj)
+        obj2 = int_to_bin(obj, width = self.width)
+        if self.swapped:
+            obj2 = swap_bytes(obj2, bytesize = self.bytesize)
+        return obj2
+    def _decode(self, obj, context):
+        if self.swapped:
+            obj = swap_bytes(obj, bytesize = self.bytesize)
+        return bin_to_int(obj, signed = self.signed)
+
+class MappingAdapter(Adapter):
+    """
+    Adapter that maps objects to other objects.
+    See SymmetricMapping and Enum.
+    
+    Parameters:
+    * subcon - the subcon to map
+    * decoding - the decoding (parsing) mapping (a dict)
+    * encoding - the encoding (building) mapping (a dict)
+    * decdefault - the default return value when the object is not found
+      in the decoding mapping. if no object is given, an exception is raised.
+      if `Pass` is used, the unmapped object will be passed as-is
+    * encdefault - the default return value when the object is not found
+      in the encoding mapping. if no object is given, an exception is raised.
+      if `Pass` is used, the unmapped object will be passed as-is
+    """
+    __slots__ = ["encoding", "decoding", "encdefault", "decdefault"]
+    def __init__(self, subcon, decoding, encoding, 
+                 decdefault = NotImplemented, encdefault = NotImplemented):
+        Adapter.__init__(self, subcon)
+        self.decoding = decoding
+        self.encoding = encoding
+        self.decdefault = decdefault
+        self.encdefault = encdefault
+    def _encode(self, obj, context):
+        try:
+            return self.encoding[obj]
+        except (KeyError, TypeError):
+            if self.encdefault is NotImplemented:
+                raise MappingError("no encoding mapping for %r [%s]" % (
+                    obj, self.subcon.name))
+            if self.encdefault is Pass:
+                return obj
+            return self.encdefault
+    def _decode(self, obj, context):
+        try:
+            return self.decoding[obj]
+        except (KeyError, TypeError):
+            if self.decdefault is NotImplemented:
+                raise MappingError("no decoding mapping for %r [%s]"  % (
+                    obj, self.subcon.name))
+            if self.decdefault is Pass:
+                return obj
+            return self.decdefault
+
+class FlagsAdapter(Adapter):
+    """
+    Adapter for flag fields. Each flag is extracted from the number, resulting
+    in a FlagsContainer object. Not intended for direct usage.
+    See FlagsEnum.
+    
+    Parameters
+    * subcon - the subcon to extract
+    * flags - a dictionary mapping flag-names to their value
+    """
+    __slots__ = ["flags"]
+    def __init__(self, subcon, flags):
+        Adapter.__init__(self, subcon)
+        self.flags = flags
+    def _encode(self, obj, context):
+        flags = 0
+        for name, value in self.flags.iteritems():
+            if getattr(obj, name, False):
+                flags |= value
+        return flags
+    def _decode(self, obj, context):
+        obj2 = FlagsContainer()
+        for name, value in self.flags.iteritems():
+            setattr(obj2, name, bool(obj & value))
+        return obj2
+
+class StringAdapter(Adapter):
+    """
+    Adapter for strings. Converts a sequence of characters into a python 
+    string, and optionally handles character encoding.
+    See String.
+    
+    Parameters:
+    * subcon - the subcon to convert
+    * encoding - the character encoding name (e.g., "utf8"), or None to 
+      return raw bytes (usually 8-bit ASCII).
+    """
+    __slots__ = ["encoding"]
+    def __init__(self, subcon, encoding = None):
+        Adapter.__init__(self, subcon)
+        self.encoding = encoding
+    def _encode(self, obj, context):
+        if self.encoding:
+            obj = obj.encode(self.encoding)
+        return obj
+    def _decode(self, obj, context):
+        obj = "".join(obj)
+        if self.encoding:
+            obj = obj.decode(self.encoding)
+        return obj
+
+class PaddedStringAdapter(Adapter):
+    r"""
+    Adapter for padded strings.
+    See String.
+    
+    Parameters:
+    * subcon - the subcon to adapt
+    * padchar - the padding character. default is "\x00".
+    * paddir - the direction where padding is placed ("right", "left", or 
+      "center"). the default is "right". 
+    * trimdir - the direction where trimming will take place ("right" or 
+      "left"). the default is "right". trimming is only meaningful for
+      building, when the given string is too long. 
+    """
+    __slots__ = ["padchar", "paddir", "trimdir"]
+    def __init__(self, subcon, padchar = "\x00", paddir = "right", 
+                 trimdir = "right"):
+        if paddir not in ("right", "left", "center"):
+            raise ValueError("paddir must be 'right', 'left' or 'center'", 
+                paddir)
+        if trimdir not in ("right", "left"):
+            raise ValueError("trimdir must be 'right' or 'left'", trimdir)
+        Adapter.__init__(self, subcon)
+        self.padchar = padchar
+        self.paddir = paddir
+        self.trimdir = trimdir
+    def _decode(self, obj, context):
+        if self.paddir == "right":
+            obj = obj.rstrip(self.padchar)
+        elif self.paddir == "left":
+            obj = obj.lstrip(self.padchar)
+        else:
+            obj = obj.strip(self.padchar)
+        return obj
+    def _encode(self, obj, context):
+        size = self._sizeof(context)
+        if self.paddir == "right":
+            obj = obj.ljust(size, self.padchar)
+        elif self.paddir == "left":
+            obj = obj.rjust(size, self.padchar)
+        else:
+            obj = obj.center(size, self.padchar)
+        if len(obj) > size:
+            if self.trimdir == "right":
+                obj = obj[:size]
+            else:
+                obj = obj[-size:]
+        return obj
+
+class LengthValueAdapter(Adapter):
+    """
+    Adapter for length-value pairs. It extracts only the value from the 
+    pair, and calculates the length based on the value.
+    See PrefixedArray and PascalString.
+    
+    Parameters:
+    * subcon - the subcon returning a length-value pair
+    """
+    __slots__ = []
+    def _encode(self, obj, context):
+        return (len(obj), obj)
+    def _decode(self, obj, context):
+        return obj[1]
+
+class CStringAdapter(StringAdapter):
+    r"""
+    Adapter for C-style strings (strings terminated by a terminator char).
+    
+    Parameters:
+    * subcon - the subcon to convert
+    * terminators - a sequence of terminator chars. default is "\x00".
+    * encoding - the character encoding to use (e.g., "utf8"), or None to
+      return raw-bytes. the terminator characters are not affected by the 
+      encoding.
+    """
+    __slots__ = ["terminators"]
+    def __init__(self, subcon, terminators = "\x00", encoding = None):
+        StringAdapter.__init__(self, subcon, encoding = encoding)
+        self.terminators = terminators
+    def _encode(self, obj, context):
+        return StringAdapter._encode(self, obj, context) + self.terminators[0]
+    def _decode(self, obj, context):
+        return StringAdapter._decode(self, obj[:-1], context)
+
+class TunnelAdapter(Adapter):
+    """
+    Adapter for tunneling (as in protocol tunneling). A tunnel is construct
+    nested upon another (layering). For parsing, the lower layer first parses
+    the data (note: it must return a string!), then the upper layer is called
+    to parse that data (bottom-up). For building it works in a top-down manner;
+    first the upper layer builds the data, then the lower layer takes it and
+    writes it to the stream.
+    
+    Parameters:
+    * subcon - the lower layer subcon
+    * inner_subcon - the upper layer (tunneled/nested) subcon
+    
+    Example:
+    # a pascal string containing compressed data (zlib encoding), so first
+    # the string is read, decompressed, and finally re-parsed as an array
+    # of UBInt16
+    TunnelAdapter(
+        PascalString("data", encoding = "zlib"),
+        GreedyRange(UBInt16("elements"))
+    )
+    """
+    __slots__ = ["inner_subcon"]
+    def __init__(self, subcon, inner_subcon):
+        Adapter.__init__(self, subcon)
+        self.inner_subcon = inner_subcon
+    def _decode(self, obj, context):
+        return self.inner_subcon._parse(StringIO(obj), context)
+    def _encode(self, obj, context):
+        stream = StringIO()
+        self.inner_subcon._build(obj, stream, context)
+        return stream.getvalue()
+
+class ExprAdapter(Adapter):
+    """
+    A generic adapter that accepts 'encoder' and 'decoder' as parameters. You
+    can use ExprAdapter instead of writing a full-blown class when only a 
+    simple expression is needed.
+    
+    Parameters:
+    * subcon - the subcon to adapt
+    * encoder - a function that takes (obj, context) and returns an encoded 
+      version of obj
+    * decoder - a function that takes (obj, context) and returns an decoded 
+      version of obj
+    
+    Example:
+    ExprAdapter(UBInt8("foo"), 
+        encoder = lambda obj, ctx: obj / 4,
+        decoder = lambda obj, ctx: obj * 4,
+    )
+    """
+    __slots__ = ["_encode", "_decode"]
+    def __init__(self, subcon, encoder, decoder):
+        Adapter.__init__(self, subcon)
+        self._encode = encoder
+        self._decode = decoder
+
+class HexDumpAdapter(Adapter):
+    """
+    Adapter for hex-dumping strings. It returns a HexString, which is a string
+    """
+    __slots__ = ["linesize"]
+    def __init__(self, subcon, linesize = 16):
+        Adapter.__init__(self, subcon)
+        self.linesize = linesize
+    def _encode(self, obj, context):
+        return obj
+    def _decode(self, obj, context):
+        return HexString(obj, linesize = self.linesize)
+
+class ConstAdapter(Adapter):
+    """
+    Adapter for enforcing a constant value ("magic numbers"). When decoding,
+    the return value is checked; when building, the value is substituted in.
+    
+    Parameters:
+    * subcon - the subcon to validate
+    * value - the expected value
+    
+    Example:
+    Const(Field("signature", 2), "MZ")
+    """
+    __slots__ = ["value"]
+    def __init__(self, subcon, value):
+        Adapter.__init__(self, subcon)
+        self.value = value
+    def _encode(self, obj, context):
+        if obj is None or obj == self.value:
+            return self.value
+        else:
+            raise ConstError("expected %r, found %r" % (self.value, obj))
+    def _decode(self, obj, context):
+        if obj != self.value:
+            raise ConstError("expected %r, found %r" % (self.value, obj))
+        return obj
+
+class SlicingAdapter(Adapter):
+    """
+    Adapter for slicing a list (getting a slice from that list)
+    
+    Parameters:
+    * subcon - the subcon to slice
+    * start - start index
+    * stop - stop index (or None for up-to-end)
+    * step - step (or None for every element)
+    """
+    __slots__ = ["start", "stop", "step"]
+    def __init__(self, subcon, start, stop = None):
+        Adapter.__init__(self, subcon)
+        self.start = start
+        self.stop = stop
+    def _encode(self, obj, context):
+        if self.start is None:
+            return obj
+        return [None] * self.start + obj
+    def _decode(self, obj, context):
+        return obj[self.start:self.stop]
+
+class IndexingAdapter(Adapter):
+    """
+    Adapter for indexing a list (getting a single item from that list)
+    
+    Parameters:
+    * subcon - the subcon to index
+    * index - the index of the list to get
+    """
+    __slots__ = ["index"]
+    def __init__(self, subcon, index):
+        Adapter.__init__(self, subcon)
+        if type(index) is not int:
+            raise TypeError("index must be an integer", type(index))
+        self.index = index
+    def _encode(self, obj, context):
+        return [None] * self.index + [obj]
+    def _decode(self, obj, context):
+        return obj[self.index]
+
+class PaddingAdapter(Adapter):
+    r"""
+    Adapter for padding.
+    
+    Parameters:
+    * subcon - the subcon to pad
+    * pattern - the padding pattern (character). default is "\x00")
+    * strict - whether or not to verify, during parsing, that the given 
+      padding matches the padding pattern. default is False (unstrict)
+    """
+    __slots__ = ["pattern", "strict"]
+    def __init__(self, subcon, pattern = "\x00", strict = False):
+        Adapter.__init__(self, subcon)
+        self.pattern = pattern
+        self.strict = strict
+    def _encode(self, obj, context):
+        return self._sizeof(context) * self.pattern
+    def _decode(self, obj, context):
+        if self.strict:
+            expected = self._sizeof(context) * self.pattern
+            if obj != expected:
+                raise PaddingError("expected %r, found %r" % (expected, obj))
+        return obj
+
+
+#===============================================================================
+# validators
+#===============================================================================
+class Validator(Adapter):
+    """
+    Abstract class: validates a condition on the encoded/decoded object. 
+    Override _validate(obj, context) in deriving classes.
+    
+    Parameters:
+    * subcon - the subcon to validate
+    """
+    __slots__ = []
+    def _decode(self, obj, context):
+        if not self._validate(obj, context):
+            raise ValidationError("invalid object", obj)
+        return obj
+    def _encode(self, obj, context):
+        return self._decode(obj, context)
+    def _validate(self, obj, context):
+        raise NotImplementedError()
+
+class OneOf(Validator):
+    """
+    Validates that the value is one of the listed values
+    
+    Parameters:
+    * subcon - the subcon to validate
+    * valids - a set of valid values
+    """
+    __slots__ = ["valids"]
+    def __init__(self, subcon, valids):
+        Validator.__init__(self, subcon)
+        self.valids = valids
+    def _validate(self, obj, context):
+        return obj in self.valids
+
+class NoneOf(Validator):
+    """
+    Validates that the value is none of the listed values
+    
+    Parameters:
+    * subcon - the subcon to validate
+    * invalids - a set of invalid values
+    """
+    __slots__ = ["invalids"]
+    def __init__(self, subcon, invalids):
+        Validator.__init__(self, subcon)
+        self.invalids = invalids
+    def _validate(self, obj, context):
+        return obj not in self.invalids
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/elftools/construct/core.py b/elftools/construct/core.py
index b09382f..773d830 100644
--- a/elftools/construct/core.py
+++ b/elftools/construct/core.py
@@ -1,1217 +1,1217 @@
-from lib import StringIO, Packer

-from lib import Container, ListContainer, AttrDict, LazyContainer

-

-

-#===============================================================================

-# exceptions

-#===============================================================================

-class ConstructError(Exception):

-    __slots__ = []

-class FieldError(ConstructError):

-    __slots__ = []

-class SizeofError(ConstructError):

-    __slots__ = []

-class AdaptationError(ConstructError):

-    __slots__ = []

-class ArrayError(ConstructError):

-    __slots__ = []

-class RangeError(ConstructError):

-    __slots__ = []

-class SwitchError(ConstructError):

-    __slots__ = []

-class SelectError(ConstructError):

-    __slots__ = []

-class TerminatorError(ConstructError):

-    __slots__ = []

-

-#===============================================================================

-# abstract constructs

-#===============================================================================

-class Construct(object):

-    """

-    The mother of all constructs!

-    

-    User API:

-    * parse(buf) - parses an in-memory buffer (usually a string)

-    * parse_stream(stream) - parses a stream (in-memory, file, pipe, ...)

-    * build(obj) - builds the object into an in-memory buffer (a string)

-    * build_stream(obj, stream) - builds the object into the given stream

-    * sizeof(context) - calculates the size of the construct, if possible,

-      based on the context

-    

-    Overriable methods for subclassing:

-    * _parse(stream, context) - low-level parse from stream

-    * _build(obj, stream, context) - low-level build to stream

-    * _sizeof(context) - low-level compute size

-    

-    Flags API:

-    * _set_flag(flag) - sets the given flag/flags

-    * _clear_flag(flag) - clears the given flag/flags

-    * _inherit_flags(*subcons) - inherits the flag of subcons

-    * _is_flag(flag) - is the flag set? (predicate)

-    

-    Overridable methods for the copy-API:

-    * __getstate__() - returns a dict of the attributes of self

-    * __setstate__(attrs) - sets the attrs to self

-    

-    Attributes:

-    All constructs have a name and flags. The name is used for naming 

-    struct-members and context dicts. Note that the name must be a string or

-    None (if the name is not needed). A single underscore ("_") is a reserved

-    name, and so are names starting with a less-than character ("<"). The name

-    should be descriptive, short, and valid as a python identifier (although

-    these rules are not enforced). 

-    

-    The flags specify additional behavioral information about this construct.

-    The flags are used by enclosing constructs to determine a proper course 

-    of action. Usually, flags are "inherited", i.e., an enclosing construct

-    inherits the flags of its subconstruct. The enclosing construct may

-    set new flags or clear existing ones, as necessary.

-        

-    For example, if FLAG_COPY_CONTEXT is set, repeaters will pass a copy of 

-    the context for each iteration, which is necessary for OnDemand parsing.

-    """

-    FLAG_COPY_CONTEXT          = 0x0001

-    FLAG_DYNAMIC               = 0x0002

-    FLAG_EMBED                 = 0x0004

-    FLAG_NESTING               = 0x0008

-    

-    __slots__ = ["name", "conflags"]

-    def __init__(self, name, flags = 0):

-        if name is not None:

-            if type(name) is not str:

-                raise TypeError("name must be a string or None", name)

-            if name == "_" or name.startswith("<"):

-                raise ValueError("reserved name", name)

-        self.name = name

-        self.conflags = flags

-    def __repr__(self):

-        return "%s(%r)" % (self.__class__.__name__, self.name)

-    

-    def _set_flag(self, flag):

-        self.conflags |= flag

-    def _clear_flag(self, flag):

-        self.conflags &= ~flag

-    def _inherit_flags(self, *subcons):

-        for sc in subcons:

-            self._set_flag(sc.conflags)

-    def _is_flag(self, flag):

-        return bool(self.conflags & flag)

-    

-    def __getstate__(self):

-        attrs = {}

-        if hasattr(self, "__dict__"):

-            attrs.update(self.__dict__)

-        slots = []

-        c = self.__class__

-        while c is not None:

-            if hasattr(c, "__slots__"):

-                slots.extend(c.__slots__)

-            c = c.__base__

-        for name in slots:

-            if hasattr(self, name):

-                attrs[name] = getattr(self, name)

-        return attrs

-    def __setstate__(self, attrs):

-        for name, value in attrs.iteritems():

-            setattr(self, name, value)

-    def __copy__(self):

-        """returns a copy of this construct"""

-        self2 = object.__new__(self.__class__)

-        self2.__setstate__(self.__getstate__())

-        return self2

-    

-    def parse(self, data):

-        """parses data given as a buffer or a string (in-memory)"""

-        return self.parse_stream(StringIO(data))

-    def parse_stream(self, stream):

-        """parses data read directly from a stream"""

-        return self._parse(stream, AttrDict())

-    def _parse(self, stream, context):

-        raise NotImplementedError()

-    

-    def build(self, obj):

-        """builds an object in a string (in memory)"""

-        stream = StringIO()

-        self.build_stream(obj, stream)

-        return stream.getvalue()

-    def build_stream(self, obj, stream):

-        """builds an object into a stream"""

-        self._build(obj, stream, AttrDict())

-    def _build(self, obj, stream, context):

-        raise NotImplementedError()

-    

-    def sizeof(self, context = None):

-        """calculates the size of the construct (if possible) using the 

-        given context"""

-        if context is None:

-            context = AttrDict()

-        return self._sizeof(context)

-    def _sizeof(self, context):

-        raise SizeofError("can't calculate size")

-

-class Subconstruct(Construct):

-    """

-    Abstract subconstruct (wraps an inner construct, inheriting it's 

-    name and flags). 

-    

-    Parameters:

-    * subcon - the construct to wrap

-    """

-    __slots__ = ["subcon"]

-    def __init__(self, subcon):

-        Construct.__init__(self, subcon.name, subcon.conflags)

-        self.subcon = subcon

-    def _parse(self, stream, context):

-        return self.subcon._parse(stream, context)

-    def _build(self, obj, stream, context):

-        self.subcon._build(obj, stream, context)

-    def _sizeof(self, context):

-        return self.subcon._sizeof(context)

-

-class Adapter(Subconstruct):

-    """

-    Abstract adapter: calls _decode for parsing and _encode for building.

-    

-    Parameters:

-    * subcon - the construct to wrap

-    """

-    __slots__ = []

-    def _parse(self, stream, context):

-        return self._decode(self.subcon._parse(stream, context), context)

-    def _build(self, obj, stream, context):

-        self.subcon._build(self._encode(obj, context), stream, context)

-    def _decode(self, obj, context):

-        raise NotImplementedError()

-    def _encode(self, obj, context):

-        raise NotImplementedError()

-

-

-#===============================================================================

-# primitives

-#===============================================================================

-def _read_stream(stream, length):

-    if length < 0:

-        raise ValueError("length must be >= 0", length)

-    data = stream.read(length)

-    if len(data) != length:

-        raise FieldError("expected %d, found %d" % (length, len(data)))

-    return data

-

-def _write_stream(stream, length, data):

-    if length < 0:

-        raise ValueError("length must be >= 0", length)

-    if len(data) != length:

-        raise FieldError("expected %d, found %d" % (length, len(data)))

-    stream.write(data)

-

-class StaticField(Construct):

-    """

-    A field of a fixed size

-    

-    Parameters:

-    * name - the name of the field

-    * length - the length (an integer)

-    

-    Example:

-    StaticField("foo", 5)

-    """

-    __slots__ = ["length"]

-    def __init__(self, name, length):

-        Construct.__init__(self, name)

-        self.length = length

-    def _parse(self, stream, context):

-        return _read_stream(stream, self.length)

-    def _build(self, obj, stream, context):

-        _write_stream(stream, self.length, obj)

-    def _sizeof(self, context):

-        return self.length

-

-class FormatField(StaticField):

-    """

-    A field that uses python's built-in struct module to pack/unpack data

-    according to a format string.

-    Note: this field has been originally implemented as an Adapter, but it 

-    was made a construct for performance reasons.

-    

-    Parameters:

-    * name - the name

-    * endianity - "<" for little endian, ">" for big endian, or "=" for native

-    * format - a single format character

-    

-    Example:

-    FormatField("foo", ">", "L")

-    """

-    __slots__ = ["packer"]

-    def __init__(self, name, endianity, format):

-        if endianity not in (">", "<", "="):

-            raise ValueError("endianity must be be '=', '<', or '>'", 

-                endianity)

-        if len(format) != 1:

-            raise ValueError("must specify one and only one format char")

-        self.packer = Packer(endianity + format)

-        StaticField.__init__(self, name, self.packer.size)

-    def __getstate__(self):

-        attrs = StaticField.__getstate__(self)

-        attrs["packer"] = attrs["packer"].format

-        return attrs

-    def __setstate__(self, attrs):

-        attrs["packer"] = Packer(attrs["packer"])

-        return StaticField.__setstate__(attrs)

-    def _parse(self, stream, context):

-        try:

-            return self.packer.unpack(_read_stream(stream, self.length))[0]

-        except Exception, ex:

-            raise FieldError(ex)

-    def _build(self, obj, stream, context):

-        try:

-            _write_stream(stream, self.length, self.packer.pack(obj))

-        except Exception, ex:

-            raise FieldError(ex)

-

-class MetaField(Construct):

-    """

-    A field of a meta-length. The length is computed at runtime based on

-    the context.

-    

-    Parameters:

-    * name - the name of the field

-    * lengthfunc - a function that takes the context as a parameter and return

-      the length of the field

-    

-    Example:

-    MetaField("foo", lambda ctx: 5)

-    """

-    __slots__ = ["lengthfunc"]

-    def __init__(self, name, lengthfunc):

-        Construct.__init__(self, name)

-        self.lengthfunc = lengthfunc

-        self._set_flag(self.FLAG_DYNAMIC)

-    def _parse(self, stream, context):

-        return _read_stream(stream, self.lengthfunc(context))

-    def _build(self, obj, stream, context):

-        _write_stream(stream, self.lengthfunc(context), obj)

-    def _sizeof(self, context):

-        return self.lengthfunc(context)

-

-

-#===============================================================================

-# arrays and repeaters

-#===============================================================================

-class MetaArray(Subconstruct):

-    """

-    An array (repeater) of a meta-count. The array will iterate exactly 

-    `countfunc()` times. Will raise ArrayError if less elements are found.

-    See also Array, Range and RepeatUntil.

-    

-    Parameters:

-    * countfunc - a function that takes the context as a parameter and returns

-      the number of elements of the array (count)

-    * subcon - the subcon to repeat `countfunc()` times

-    

-    Example:

-    MetaArray(lambda ctx: 5, UBInt8("foo"))

-    """

-    __slots__ = ["countfunc"]

-    def __init__(self, countfunc, subcon):

-        Subconstruct.__init__(self, subcon)

-        self.countfunc = countfunc

-        self._clear_flag(self.FLAG_COPY_CONTEXT)

-        self._set_flag(self.FLAG_DYNAMIC)

-    def _parse(self, stream, context):

-        obj = ListContainer()

-        c = 0

-        count = self.countfunc(context)

-        try:

-            if self.subcon.conflags & self.FLAG_COPY_CONTEXT:

-                while c < count:

-                    obj.append(self.subcon._parse(stream, context.__copy__()))

-                    c += 1

-            else:

-                while c < count:

-                    obj.append(self.subcon._parse(stream, context))

-                    c += 1

-        except ConstructError, ex:

-            raise ArrayError("expected %d, found %d" % (count, c), ex)

-        return obj

-    def _build(self, obj, stream, context):

-        count = self.countfunc(context)

-        if len(obj) != count:

-            raise ArrayError("expected %d, found %d" % (count, len(obj)))

-        if self.subcon.conflags & self.FLAG_COPY_CONTEXT:

-            for subobj in obj:

-                self.subcon._build(subobj, stream, context.__copy__())

-        else:

-            for subobj in obj:

-                self.subcon._build(subobj, stream, context)

-    def _sizeof(self, context):

-        return self.subcon._sizeof(context) * self.countfunc(context)

-

-class Range(Subconstruct):

-    """

-    A range-array. The subcon will iterate between `mincount` to `maxcount`

-    times. If less than `mincount` elements are found, raises RangeError.

-    See also GreedyRange and OptionalGreedyRange.

-    

-    Notes:

-    * requires a seekable stream.

-    

-    Parameters:

-    * mincount - the minimal count (an integer)

-    * maxcount - the maximal count (an integer)

-    * subcon - the subcon to repeat

-    

-    Example:

-    Range(5, 8, UBInt8("foo"))

-    """

-    __slots__ = ["mincount", "maxcout"]

-    def __init__(self, mincount, maxcout, subcon):

-        Subconstruct.__init__(self, subcon)

-        self.mincount = mincount

-        self.maxcout = maxcout

-        self._clear_flag(self.FLAG_COPY_CONTEXT)

-        self._set_flag(self.FLAG_DYNAMIC)

-    def _parse(self, stream, context):

-        obj = ListContainer()

-        c = 0

-        try:

-            if self.subcon.conflags & self.FLAG_COPY_CONTEXT:

-                while c < self.maxcout:

-                    pos = stream.tell()

-                    obj.append(self.subcon._parse(stream, context.__copy__()))

-                    c += 1

-            else:

-                while c < self.maxcout:

-                    pos = stream.tell()

-                    obj.append(self.subcon._parse(stream, context))

-                    c += 1

-        except ConstructError:

-            if c < self.mincount:

-                raise RangeError("expected %d to %d, found %d" % 

-                    (self.mincount, self.maxcout, c))

-            stream.seek(pos)

-        return obj

-    def _build(self, obj, stream, context):

-        if len(obj) < self.mincount or len(obj) > self.maxcout:

-            raise RangeError("expected %d to %d, found %d" % 

-                (self.mincount, self.maxcout, len(obj)))

-        cnt = 0

-        try:

-            if self.subcon.conflags & self.FLAG_COPY_CONTEXT:

-                for subobj in obj:

-                    self.subcon._build(subobj, stream, context.__copy__())

-                    cnt += 1

-            else:

-                for subobj in obj:

-                    self.subcon._build(subobj, stream, context)

-                    cnt += 1

-        except ConstructError:

-            if cnt < self.mincount:

-                raise RangeError("expected %d to %d, found %d" % 

-                    (self.mincount, self.maxcout, len(obj)))

-    def _sizeof(self, context):

-        raise SizeofError("can't calculate size")

-

-class RepeatUntil(Subconstruct):

-    """

-    An array that repeat until the predicate indicates it to stop. Note that

-    the last element (which caused the repeat to exit) is included in the 

-    return value.

-    

-    Parameters:

-    * predicate - a predicate function that takes (obj, context) and returns

-      True if the stop-condition is met, or False to continue.

-    * subcon - the subcon to repeat.

-    

-    Example:

-    # will read chars until \x00 (inclusive)

-    RepeatUntil(lambda obj, ctx: obj == "\x00",

-        Field("chars", 1)

-    )

-    """

-    __slots__ = ["predicate"]

-    def __init__(self, predicate, subcon):

-        Subconstruct.__init__(self, subcon)

-        self.predicate = predicate

-        self._clear_flag(self.FLAG_COPY_CONTEXT)

-        self._set_flag(self.FLAG_DYNAMIC)

-    def _parse(self, stream, context):

-        obj = []

-        try:

-            if self.subcon.conflags & self.FLAG_COPY_CONTEXT:

-                while True:

-                    subobj = self.subcon._parse(stream, context.__copy__())

-                    obj.append(subobj)

-                    if self.predicate(subobj, context):

-                        break

-            else:

-                while True:

-                    subobj = self.subcon._parse(stream, context)

-                    obj.append(subobj)

-                    if self.predicate(subobj, context):

-                        break

-        except ConstructError, ex:

-            raise ArrayError("missing terminator", ex)

-        return obj

-    def _build(self, obj, stream, context):

-        terminated = False

-        if self.subcon.conflags & self.FLAG_COPY_CONTEXT:

-            for subobj in obj:

-                self.subcon._build(subobj, stream, context.__copy__())

-                if self.predicate(subobj, context):

-                    terminated = True

-                    break

-        else:

-            for subobj in obj:

-                self.subcon._build(subobj, stream, context.__copy__())

-                if self.predicate(subobj, context):

-                    terminated = True

-                    break

-        if not terminated:

-            raise ArrayError("missing terminator")

-    def _sizeof(self, context):

-        raise SizeofError("can't calculate size")

-

-

-#===============================================================================

-# structures and sequences

-#===============================================================================

-class Struct(Construct):

-    """

-    A sequence of named constructs, similar to structs in C. The elements are

-    parsed and built in the order they are defined.

-    See also Embedded.

-    

-    Parameters:

-    * name - the name of the structure

-    * subcons - a sequence of subconstructs that make up this structure.

-    * nested - a keyword-only argument that indicates whether this struct 

-      creates a nested context. The default is True. This parameter is 

-      considered "advanced usage", and may be removed in the future.

-    

-    Example:

-    Struct("foo",

-        UBInt8("first_element"),

-        UBInt16("second_element"),

-        Padding(2),

-        UBInt8("third_element"),

-    )

-    """

-    __slots__ = ["subcons", "nested"]

-    def __init__(self, name, *subcons, **kw):

-        self.nested = kw.pop("nested", True)

-        if kw:

-            raise TypeError("the only keyword argument accepted is 'nested'", kw)

-        Construct.__init__(self, name)

-        self.subcons = subcons

-        self._inherit_flags(*subcons)

-        self._clear_flag(self.FLAG_EMBED)

-    def _parse(self, stream, context):

-        if "<obj>" in context:

-            obj = context["<obj>"]

-            del context["<obj>"]

-        else:

-            obj = Container()

-            if self.nested:

-                context = AttrDict(_ = context)

-        for sc in self.subcons:

-            if sc.conflags & self.FLAG_EMBED:

-                context["<obj>"] = obj

-                sc._parse(stream, context)

-            else:

-                subobj = sc._parse(stream, context)

-                if sc.name is not None:

-                    obj[sc.name] = subobj

-                    context[sc.name] = subobj

-        return obj

-    def _build(self, obj, stream, context):

-        if "<unnested>" in context:

-            del context["<unnested>"]

-        elif self.nested:

-            context = AttrDict(_ = context)

-        for sc in self.subcons:

-            if sc.conflags & self.FLAG_EMBED:

-                context["<unnested>"] = True

-                subobj = obj

-            elif sc.name is None:

-                subobj = None

-            else:

-                subobj = getattr(obj, sc.name)

-                context[sc.name] = subobj

-            sc._build(subobj, stream, context)

-    def _sizeof(self, context):

-        if self.nested:

-            context = AttrDict(_ = context)

-        return sum(sc._sizeof(context) for sc in self.subcons)

-

-class Sequence(Struct):

-    """

-    A sequence of unnamed constructs. The elements are parsed and built in the

-    order they are defined.

-    See also Embedded.

-    

-    Parameters:

-    * name - the name of the structure

-    * subcons - a sequence of subconstructs that make up this structure.

-    * nested - a keyword-only argument that indicates whether this struct 

-      creates a nested context. The default is True. This parameter is 

-      considered "advanced usage", and may be removed in the future.

-    

-    Example:

-    Sequence("foo",

-        UBInt8("first_element"),

-        UBInt16("second_element"),

-        Padding(2),

-        UBInt8("third_element"),

-    )

-    """

-    __slots__ = []

-    def _parse(self, stream, context):

-        if "<obj>" in context:

-            obj = context["<obj>"]

-            del context["<obj>"]

-        else:

-            obj = ListContainer()

-            if self.nested:

-                context = AttrDict(_ = context)

-        for sc in self.subcons:

-            if sc.conflags & self.FLAG_EMBED:

-                context["<obj>"] = obj

-                sc._parse(stream, context)

-            else:

-                subobj = sc._parse(stream, context)

-                if sc.name is not None:

-                    obj.append(subobj)

-                    context[sc.name] = subobj

-        return obj

-    def _build(self, obj, stream, context):

-        if "<unnested>" in context:

-            del context["<unnested>"]

-        elif self.nested:

-            context = AttrDict(_ = context)

-        objiter = iter(obj)

-        for sc in self.subcons:

-            if sc.conflags & self.FLAG_EMBED:

-                context["<unnested>"] = True

-                subobj = objiter

-            elif sc.name is None:

-                subobj = None

-            else:

-                subobj = objiter.next()

-                context[sc.name] = subobj

-            sc._build(subobj, stream, context)

-

-class Union(Construct):

-    """

-    a set of overlapping fields (like unions in C). when parsing, 

-    all fields read the same data; when building, only the first subcon

-    (called "master") is used. 

-    

-    Parameters:

-    * name - the name of the union

-    * master - the master subcon, i.e., the subcon used for building and 

-      calculating the total size

-    * subcons - additional subcons

-    

-    Example:

-    Union("what_are_four_bytes",

-        UBInt32("one_dword"),

-        Struct("two_words", UBInt16("first"), UBInt16("second")),

-        Struct("four_bytes", 

-            UBInt8("a"), 

-            UBInt8("b"), 

-            UBInt8("c"), 

-            UBInt8("d")

-        ),

-    )

-    """

-    __slots__ = ["parser", "builder"]

-    def __init__(self, name, master, *subcons, **kw):

-        Construct.__init__(self, name)

-        args = [Peek(sc) for sc in subcons]

-        args.append(MetaField(None, lambda ctx: master._sizeof(ctx)))

-        self.parser = Struct(name, Peek(master, perform_build = True), *args)

-        self.builder = Struct(name, master)

-    def _parse(self, stream, context):

-        return self.parser._parse(stream, context)

-    def _build(self, obj, stream, context):

-        return self.builder._build(obj, stream, context)

-    def _sizeof(self, context):

-        return self.builder._sizeof(context)

-

-#===============================================================================

-# conditional

-#===============================================================================

-class Switch(Construct):

-    """

-    A conditional branch. Switch will choose the case to follow based on

-    the return value of keyfunc. If no case is matched, and no default value 

-    is given, SwitchError will be raised.

-    See also Pass.

-    

-    Parameters:

-    * name - the name of the construct

-    * keyfunc - a function that takes the context and returns a key, which 

-      will ne used to choose the relevant case.

-    * cases - a dictionary mapping keys to constructs. the keys can be any 

-      values that may be returned by keyfunc.

-    * default - a default value to use when the key is not found in the cases.

-      if not supplied, an exception will be raised when the key is not found.

-      You can use the builtin construct Pass for 'do-nothing'.

-    * include_key - whether or not to include the key in the return value

-      of parsing. defualt is False.

-    

-    Example:

-    Struct("foo",

-        UBInt8("type"),

-        Switch("value", lambda ctx: ctx.type, {

-                1 : UBInt8("spam"),

-                2 : UBInt16("spam"),

-                3 : UBInt32("spam"),

-                4 : UBInt64("spam"),

-            }

-        ),

-    )

-    """

-    

-    class NoDefault(Construct):

-        def _parse(self, stream, context):

-            raise SwitchError("no default case defined")

-        def _build(self, obj, stream, context):

-            raise SwitchError("no default case defined")

-        def _sizeof(self, context):

-            raise SwitchError("no default case defined")

-    NoDefault = NoDefault("NoDefault")

-    

-    __slots__ = ["subcons", "keyfunc", "cases", "default", "include_key"]

-    

-    def __init__(self, name, keyfunc, cases, default = NoDefault, 

-                 include_key = False):

-        Construct.__init__(self, name)

-        self._inherit_flags(*cases.values())

-        self.keyfunc = keyfunc

-        self.cases = cases

-        self.default = default

-        self.include_key = include_key

-        self._inherit_flags(*cases.values())

-        self._set_flag(self.FLAG_DYNAMIC)

-    def _parse(self, stream, context):

-        key = self.keyfunc(context)

-        obj = self.cases.get(key, self.default)._parse(stream, context)

-        if self.include_key:

-            return key, obj

-        else:

-            return obj

-    def _build(self, obj, stream, context):

-        if self.include_key:

-            key, obj = obj

-        else:

-            key = self.keyfunc(context)

-        case = self.cases.get(key, self.default)

-        case._build(obj, stream, context)

-    def _sizeof(self, context):

-        case = self.cases.get(self.keyfunc(context), self.default)

-        return case._sizeof(context)

-

-class Select(Construct):

-    """

-    Selects the first matching subconstruct. It will literally try each of

-    the subconstructs, until one matches.

-    

-    Notes:

-    * requires a seekable stream.

-    

-    Parameters:

-    * name - the name of the construct

-    * subcons - the subcons to try (order-sensitive)

-    * include_name - a keyword only argument, indicating whether to include 

-      the name of the selected subcon in the return value of parsing. default

-      is false.

-    

-    Example:

-    Select("foo",

-        UBInt64("large"),

-        UBInt32("medium"),

-        UBInt16("small"),

-        UBInt8("tiny"),

-    )

-    """

-    __slots__ = ["subcons", "include_name"]

-    def __init__(self, name, *subcons, **kw):

-        include_name = kw.pop("include_name", False)

-        if kw:

-            raise TypeError("the only keyword argument accepted "

-                "is 'include_name'", kw)

-        Construct.__init__(self, name)

-        self.subcons = subcons

-        self.include_name = include_name

-        self._inherit_flags(*subcons)

-        self._set_flag(self.FLAG_DYNAMIC)

-    def _parse(self, stream, context):

-        for sc in self.subcons:

-            pos = stream.tell()

-            context2 = context.__copy__()

-            try:

-                obj = sc._parse(stream, context2)

-            except ConstructError:

-                stream.seek(pos)

-            else:

-                context.__update__(context2)

-                if self.include_name:

-                    return sc.name, obj

-                else:

-                    return obj

-        raise SelectError("no subconstruct matched")

-    def _build(self, obj, stream, context):

-        if self.include_name:

-            name, obj = obj

-            for sc in self.subcons:

-                if sc.name == name:

-                    sc._build(obj, stream, context)

-                    return

-        else: 

-            for sc in self.subcons:

-                stream2 = StringIO()

-                context2 = context.__copy__()

-                try:

-                    sc._build(obj, stream2, context2)

-                except Exception:

-                    pass

-                else:

-                    context.__update__(context2)

-                    stream.write(stream2.getvalue())

-                    return

-        raise SelectError("no subconstruct matched", obj)

-    def _sizeof(self, context):

-        raise SizeofError("can't calculate size")

-

-

-#===============================================================================

-# stream manipulation

-#===============================================================================

-class Pointer(Subconstruct):

-    """

-    Changes the stream position to a given offset, where the construction

-    should take place, and restores the stream position when finished.

-    See also Anchor, OnDemand and OnDemandPointer.

-    

-    Notes:

-    * requires a seekable stream.

-    

-    Parameters:

-    * offsetfunc: a function that takes the context and returns an absolute 

-      stream position, where the construction would take place

-    * subcon - the subcon to use at `offsetfunc()`

-    

-    Example:

-    Struct("foo",

-        UBInt32("spam_pointer"),

-        Pointer(lambda ctx: ctx.spam_pointer,

-            Array(5, UBInt8("spam"))

-        )

-    )

-    """

-    __slots__ = ["offsetfunc"]

-    def __init__(self, offsetfunc, subcon):

-        Subconstruct.__init__(self, subcon)

-        self.offsetfunc = offsetfunc

-    def _parse(self, stream, context):

-        newpos = self.offsetfunc(context)

-        origpos = stream.tell()

-        stream.seek(newpos)

-        obj = self.subcon._parse(stream, context)

-        stream.seek(origpos)

-        return obj

-    def _build(self, obj, stream, context):

-        newpos = self.offsetfunc(context)

-        origpos = stream.tell()

-        stream.seek(newpos)

-        self.subcon._build(obj, stream, context)

-        stream.seek(origpos)

-    def _sizeof(self, context):

-        return 0

-

-class Peek(Subconstruct):

-    """

-    Peeks at the stream: parses without changing the stream position.

-    See also Union. If the end of the stream is reached when peeking,

-    returns None.

-    

-    Notes:

-    * requires a seekable stream.

-    

-    Parameters:

-    * subcon - the subcon to peek at

-    * perform_build - whether or not to perform building. by default this 

-      parameter is set to False, meaning building is a no-op.

-    

-    Example:

-    Peek(UBInt8("foo"))

-    """

-    __slots__ = ["perform_build"]

-    def __init__(self, subcon, perform_build = False):

-        Subconstruct.__init__(self, subcon)

-        self.perform_build = perform_build

-    def _parse(self, stream, context):

-        pos = stream.tell()

-        try:

-            try:

-                return self.subcon._parse(stream, context)

-            except FieldError:

-                pass

-        finally:

-            stream.seek(pos)

-    def _build(self, obj, stream, context):

-        if self.perform_build:

-            self.subcon._build(obj, stream, context)

-    def _sizeof(self, context):

-        return 0

-

-class OnDemand(Subconstruct):

-    """

-    Allows for on-demand (lazy) parsing. When parsing, it will return a 

-    LazyContainer that represents a pointer to the data, but does not actually

-    parses it from stream until it's "demanded".

-    By accessing the 'value' property of LazyContainers, you will demand the 

-    data from the stream. The data will be parsed and cached for later use.

-    You can use the 'has_value' property to know whether the data has already 

-    been demanded.

-    See also OnDemandPointer.

-    

-    Notes:

-    * requires a seekable stream.

-    

-    Parameters:

-    * subcon - 

-    * advance_stream - whether or not to advance the stream position. by 

-      default this is True, but if subcon is a pointer, this should be False.

-    * force_build - whether or not to force build. If set to False, and the

-      LazyContainer has not been demaned, building is a no-op.

-    

-    Example:

-    OnDemand(Array(10000, UBInt8("foo"))

-    """

-    __slots__ = ["advance_stream", "force_build"]

-    def __init__(self, subcon, advance_stream = True, force_build = True):

-        Subconstruct.__init__(self, subcon)

-        self.advance_stream = advance_stream

-        self.force_build = force_build

-    def _parse(self, stream, context):

-        obj = LazyContainer(self.subcon, stream, stream.tell(), context)

-        if self.advance_stream:

-            stream.seek(self.subcon._sizeof(context), 1)

-        return obj

-    def _build(self, obj, stream, context):

-        if not isinstance(obj, LazyContainer):

-            self.subcon._build(obj, stream, context)

-        elif self.force_build or obj.has_value:

-            self.subcon._build(obj.value, stream, context)

-        elif self.advance_stream:

-            stream.seek(self.subcon._sizeof(context), 1)

-

-class Buffered(Subconstruct):

-    """

-    Creates an in-memory buffered stream, which can undergo encoding and 

-    decoding prior to being passed on to the subconstruct.

-    See also Bitwise.

-    

-    Note:

-    * Do not use pointers inside Buffered

-    

-    Parameters:

-    * subcon - the subcon which will operate on the buffer

-    * encoder - a function that takes a string and returns an encoded

-      string (used after building)

-    * decoder - a function that takes a string and returns a decoded

-      string (used before parsing)

-    * resizer - a function that takes the size of the subcon and "adjusts"

-      or "resizes" it according to the encoding/decoding process.

-    

-    Example:

-    Buffered(BitField("foo", 16),

-        encoder = decode_bin,

-        decoder = encode_bin,

-        resizer = lambda size: size / 8,

-    )

-    """

-    __slots__ = ["encoder", "decoder", "resizer"]

-    def __init__(self, subcon, decoder, encoder, resizer):

-        Subconstruct.__init__(self, subcon)

-        self.encoder = encoder

-        self.decoder = decoder

-        self.resizer = resizer

-    def _parse(self, stream, context):

-        data = _read_stream(stream, self._sizeof(context))

-        stream2 = StringIO(self.decoder(data))

-        return self.subcon._parse(stream2, context)

-    def _build(self, obj, stream, context):

-        size = self._sizeof(context)

-        stream2 = StringIO()

-        self.subcon._build(obj, stream2, context)

-        data = self.encoder(stream2.getvalue())

-        assert len(data) == size

-        _write_stream(stream, self._sizeof(context), data)

-    def _sizeof(self, context):

-        return self.resizer(self.subcon._sizeof(context))

-

-class Restream(Subconstruct):

-    """

-    Wraps the stream with a read-wrapper (for parsing) or a 

-    write-wrapper (for building). The stream wrapper can buffer the data

-    internally, reading it from- or writing it to the underlying stream 

-    as needed. For example, BitStreamReader reads whole bytes from the 

-    underlying stream, but returns them as individual bits. 

-    See also Bitwise.

-    

-    When the parsing or building is done, the stream's close method 

-    will be invoked. It can perform any finalization needed for the stream

-    wrapper, but it must not close the underlying stream.

-    

-    Note:

-    * Do not use pointers inside Restream

-    

-    Parameters:

-    * subcon - the subcon

-    * stream_reader - the read-wrapper

-    * stream_writer - the write wrapper

-    * resizer - a function that takes the size of the subcon and "adjusts"

-      or "resizes" it according to the encoding/decoding process.

-    

-    Example:

-    Restream(BitField("foo", 16),

-        stream_reader = BitStreamReader,

-        stream_writer = BitStreamWriter,

-        resizer = lambda size: size / 8,

-    )

-    """

-    __slots__ = ["stream_reader", "stream_writer", "resizer"]

-    def __init__(self, subcon, stream_reader, stream_writer, resizer):

-        Subconstruct.__init__(self, subcon)

-        self.stream_reader = stream_reader

-        self.stream_writer = stream_writer

-        self.resizer = resizer

-    def _parse(self, stream, context):

-        stream2 = self.stream_reader(stream)

-        obj = self.subcon._parse(stream2, context)

-        stream2.close()

-        return obj

-    def _build(self, obj, stream, context):

-        stream2 = self.stream_writer(stream)

-        self.subcon._build(obj, stream2, context)

-        stream2.close()

-    def _sizeof(self, context):

-        return self.resizer(self.subcon._sizeof(context))

-

-

-#===============================================================================

-# miscellaneous

-#===============================================================================

-class Reconfig(Subconstruct):

-    """

-    Reconfigures a subconstruct. Reconfig can be used to change the name and

-    set and clear flags of the inner subcon.

-    

-    Parameters:

-    * name - the new name

-    * subcon - the subcon to reconfigure

-    * setflags - the flags to set (default is 0)

-    * clearflags - the flags to clear (default is 0)

-    

-    Example:

-    Reconfig("foo", UBInt8("bar"))

-    """

-    __slots__ = []

-    def __init__(self, name, subcon, setflags = 0, clearflags = 0):

-        Construct.__init__(self, name, subcon.conflags)

-        self.subcon = subcon

-        self._set_flag(setflags)

-        self._clear_flag(clearflags)

-

-class Anchor(Construct):

-    """

-    Returns the "anchor" (stream position) at the point where it's inserted.

-    Useful for adjusting relative offsets to absolute positions, or to measure

-    sizes of constructs.

-    absolute pointer = anchor + relative offset

-    size = anchor_after - anchor_before

-    See also Pointer.

-    

-    Notes:

-    * requires a seekable stream.

-    

-    Parameters:

-    * name - the name of the anchor

-    

-    Example:

-    Struct("foo",

-        Anchor("base"),

-        UBInt8("relative_offset"),

-        Pointer(lambda ctx: ctx.relative_offset + ctx.base,

-            UBInt8("data")

-        )

-    )

-    """

-    __slots__ = []

-    def _parse(self, stream, context):

-        return stream.tell()

-    def _build(self, obj, stream, context):

-        context[self.name] = stream.tell()

-    def _sizeof(self, context):

-        return 0

-

-class Value(Construct):

-    """

-    A computed value.

-    

-    Parameters:

-    * name - the name of the value

-    * func - a function that takes the context and return the computed value

-    

-    Example:

-    Struct("foo",

-        UBInt8("width"),

-        UBInt8("height"),

-        Value("total_pixels", lambda ctx: ctx.width * ctx.height),

-    )

-    """

-    __slots__ = ["func"]

-    def __init__(self, name, func):

-        Construct.__init__(self, name)

-        self.func = func

-        self._set_flag(self.FLAG_DYNAMIC)

-    def _parse(self, stream, context):

-        return self.func(context)

-    def _build(self, obj, stream, context):

-        context[self.name] = self.func(context)

-    def _sizeof(self, context):

-        return 0

-

-#class Dynamic(Construct):

-#    """

-#    Dynamically creates a construct and uses it for parsing and building.

-#    This allows you to create change the construction tree on the fly.

-#    Deprecated.

-#    

-#    Parameters:

-#    * name - the name of the construct

-#    * factoryfunc - a function that takes the context and returns a new 

-#      construct object which will be used for parsing and building.

-#    

-#    Example:

-#    def factory(ctx):

-#        if ctx.bar == 8:

-#            return UBInt8("spam")

-#        if ctx.bar == 9:

-#            return String("spam", 9)

-#    

-#    Struct("foo",

-#        UBInt8("bar"),

-#        Dynamic("spam", factory),

-#    )

-#    """

-#    __slots__ = ["factoryfunc"]

-#    def __init__(self, name, factoryfunc):

-#        Construct.__init__(self, name, self.FLAG_COPY_CONTEXT)

-#        self.factoryfunc = factoryfunc

-#        self._set_flag(self.FLAG_DYNAMIC)

-#    def _parse(self, stream, context):

-#        return self.factoryfunc(context)._parse(stream, context)

-#    def _build(self, obj, stream, context):

-#        return self.factoryfunc(context)._build(obj, stream, context)

-#    def _sizeof(self, context):

-#        return self.factoryfunc(context)._sizeof(context)

-

-class LazyBound(Construct):

-    """

-    Lazily bound construct, useful for constructs that need to make cyclic 

-    references (linked-lists, expression trees, etc.).

-    

-    Parameters:

-    

-    

-    Example:

-    foo = Struct("foo",

-        UBInt8("bar"),

-        LazyBound("next", lambda: foo),

-    )

-    """

-    __slots__ = ["bindfunc", "bound"]

-    def __init__(self, name, bindfunc):

-        Construct.__init__(self, name)

-        self.bound = None

-        self.bindfunc = bindfunc

-    def _parse(self, stream, context):

-        if self.bound is None:

-            self.bound = self.bindfunc()

-        return self.bound._parse(stream, context)

-    def _build(self, obj, stream, context):

-        if self.bound is None:

-            self.bound = self.bindfunc()

-        self.bound._build(obj, stream, context)

-    def _sizeof(self, context):

-        if self.bound is None:

-            self.bound = self.bindfunc()

-        return self.bound._sizeof(context)

-

-class Pass(Construct):

-    """

-    A do-nothing construct, useful as the default case for Switch, or

-    to indicate Enums.

-    See also Switch and Enum.

-    

-    Notes:

-    * this construct is a singleton. do not try to instatiate it, as it 

-      will not work :)

-    

-    Example:

-    Pass

-    """

-    __slots__ = []

-    def _parse(self, stream, context):

-        pass

-    def _build(self, obj, stream, context):

-        assert obj is None

-    def _sizeof(self, context):

-        return 0

-Pass = Pass(None)

-

-class Terminator(Construct):

-    """

-    Asserts the end of the stream has been reached at the point it's placed.

-    You can use this to ensure no more unparsed data follows.

-    

-    Notes:

-    * this construct is a singleton. do not try to instatiate it, as it 

-      will not work :)

-    

-    Example:

-    Terminator

-    """

-    __slots__ = []

-    def _parse(self, stream, context):

-        if stream.read(1):

-            raise TerminatorError("expected end of stream")

-    def _build(self, obj, stream, context):

-        assert obj is None

-    def _sizeof(self, context):

-        return 0

-Terminator = Terminator(None)

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

+from lib import StringIO, Packer
+from lib import Container, ListContainer, AttrDict, LazyContainer
+
+
+#===============================================================================
+# exceptions
+#===============================================================================
+class ConstructError(Exception):
+    __slots__ = []
+class FieldError(ConstructError):
+    __slots__ = []
+class SizeofError(ConstructError):
+    __slots__ = []
+class AdaptationError(ConstructError):
+    __slots__ = []
+class ArrayError(ConstructError):
+    __slots__ = []
+class RangeError(ConstructError):
+    __slots__ = []
+class SwitchError(ConstructError):
+    __slots__ = []
+class SelectError(ConstructError):
+    __slots__ = []
+class TerminatorError(ConstructError):
+    __slots__ = []
+
+#===============================================================================
+# abstract constructs
+#===============================================================================
+class Construct(object):
+    """
+    The mother of all constructs!
+    
+    User API:
+    * parse(buf) - parses an in-memory buffer (usually a string)
+    * parse_stream(stream) - parses a stream (in-memory, file, pipe, ...)
+    * build(obj) - builds the object into an in-memory buffer (a string)
+    * build_stream(obj, stream) - builds the object into the given stream
+    * sizeof(context) - calculates the size of the construct, if possible,
+      based on the context
+    
+    Overriable methods for subclassing:
+    * _parse(stream, context) - low-level parse from stream
+    * _build(obj, stream, context) - low-level build to stream
+    * _sizeof(context) - low-level compute size
+    
+    Flags API:
+    * _set_flag(flag) - sets the given flag/flags
+    * _clear_flag(flag) - clears the given flag/flags
+    * _inherit_flags(*subcons) - inherits the flag of subcons
+    * _is_flag(flag) - is the flag set? (predicate)
+    
+    Overridable methods for the copy-API:
+    * __getstate__() - returns a dict of the attributes of self
+    * __setstate__(attrs) - sets the attrs to self
+    
+    Attributes:
+    All constructs have a name and flags. The name is used for naming 
+    struct-members and context dicts. Note that the name must be a string or
+    None (if the name is not needed). A single underscore ("_") is a reserved
+    name, and so are names starting with a less-than character ("<"). The name
+    should be descriptive, short, and valid as a python identifier (although
+    these rules are not enforced). 
+    
+    The flags specify additional behavioral information about this construct.
+    The flags are used by enclosing constructs to determine a proper course 
+    of action. Usually, flags are "inherited", i.e., an enclosing construct
+    inherits the flags of its subconstruct. The enclosing construct may
+    set new flags or clear existing ones, as necessary.
+        
+    For example, if FLAG_COPY_CONTEXT is set, repeaters will pass a copy of 
+    the context for each iteration, which is necessary for OnDemand parsing.
+    """
+    FLAG_COPY_CONTEXT          = 0x0001
+    FLAG_DYNAMIC               = 0x0002
+    FLAG_EMBED                 = 0x0004
+    FLAG_NESTING               = 0x0008
+    
+    __slots__ = ["name", "conflags"]
+    def __init__(self, name, flags = 0):
+        if name is not None:
+            if type(name) is not str:
+                raise TypeError("name must be a string or None", name)
+            if name == "_" or name.startswith("<"):
+                raise ValueError("reserved name", name)
+        self.name = name
+        self.conflags = flags
+    def __repr__(self):
+        return "%s(%r)" % (self.__class__.__name__, self.name)
+    
+    def _set_flag(self, flag):
+        self.conflags |= flag
+    def _clear_flag(self, flag):
+        self.conflags &= ~flag
+    def _inherit_flags(self, *subcons):
+        for sc in subcons:
+            self._set_flag(sc.conflags)
+    def _is_flag(self, flag):
+        return bool(self.conflags & flag)
+    
+    def __getstate__(self):
+        attrs = {}
+        if hasattr(self, "__dict__"):
+            attrs.update(self.__dict__)
+        slots = []
+        c = self.__class__
+        while c is not None:
+            if hasattr(c, "__slots__"):
+                slots.extend(c.__slots__)
+            c = c.__base__
+        for name in slots:
+            if hasattr(self, name):
+                attrs[name] = getattr(self, name)
+        return attrs
+    def __setstate__(self, attrs):
+        for name, value in attrs.iteritems():
+            setattr(self, name, value)
+    def __copy__(self):
+        """returns a copy of this construct"""
+        self2 = object.__new__(self.__class__)
+        self2.__setstate__(self.__getstate__())
+        return self2
+    
+    def parse(self, data):
+        """parses data given as a buffer or a string (in-memory)"""
+        return self.parse_stream(StringIO(data))
+    def parse_stream(self, stream):
+        """parses data read directly from a stream"""
+        return self._parse(stream, AttrDict())
+    def _parse(self, stream, context):
+        raise NotImplementedError()
+    
+    def build(self, obj):
+        """builds an object in a string (in memory)"""
+        stream = StringIO()
+        self.build_stream(obj, stream)
+        return stream.getvalue()
+    def build_stream(self, obj, stream):
+        """builds an object into a stream"""
+        self._build(obj, stream, AttrDict())
+    def _build(self, obj, stream, context):
+        raise NotImplementedError()
+    
+    def sizeof(self, context = None):
+        """calculates the size of the construct (if possible) using the 
+        given context"""
+        if context is None:
+            context = AttrDict()
+        return self._sizeof(context)
+    def _sizeof(self, context):
+        raise SizeofError("can't calculate size")
+
+class Subconstruct(Construct):
+    """
+    Abstract subconstruct (wraps an inner construct, inheriting it's 
+    name and flags). 
+    
+    Parameters:
+    * subcon - the construct to wrap
+    """
+    __slots__ = ["subcon"]
+    def __init__(self, subcon):
+        Construct.__init__(self, subcon.name, subcon.conflags)
+        self.subcon = subcon
+    def _parse(self, stream, context):
+        return self.subcon._parse(stream, context)
+    def _build(self, obj, stream, context):
+        self.subcon._build(obj, stream, context)
+    def _sizeof(self, context):
+        return self.subcon._sizeof(context)
+
+class Adapter(Subconstruct):
+    """
+    Abstract adapter: calls _decode for parsing and _encode for building.
+    
+    Parameters:
+    * subcon - the construct to wrap
+    """
+    __slots__ = []
+    def _parse(self, stream, context):
+        return self._decode(self.subcon._parse(stream, context), context)
+    def _build(self, obj, stream, context):
+        self.subcon._build(self._encode(obj, context), stream, context)
+    def _decode(self, obj, context):
+        raise NotImplementedError()
+    def _encode(self, obj, context):
+        raise NotImplementedError()
+
+
+#===============================================================================
+# primitives
+#===============================================================================
+def _read_stream(stream, length):
+    if length < 0:
+        raise ValueError("length must be >= 0", length)
+    data = stream.read(length)
+    if len(data) != length:
+        raise FieldError("expected %d, found %d" % (length, len(data)))
+    return data
+
+def _write_stream(stream, length, data):
+    if length < 0:
+        raise ValueError("length must be >= 0", length)
+    if len(data) != length:
+        raise FieldError("expected %d, found %d" % (length, len(data)))
+    stream.write(data)
+
+class StaticField(Construct):
+    """
+    A field of a fixed size
+    
+    Parameters:
+    * name - the name of the field
+    * length - the length (an integer)
+    
+    Example:
+    StaticField("foo", 5)
+    """
+    __slots__ = ["length"]
+    def __init__(self, name, length):
+        Construct.__init__(self, name)
+        self.length = length
+    def _parse(self, stream, context):
+        return _read_stream(stream, self.length)
+    def _build(self, obj, stream, context):
+        _write_stream(stream, self.length, obj)
+    def _sizeof(self, context):
+        return self.length
+
+class FormatField(StaticField):
+    """
+    A field that uses python's built-in struct module to pack/unpack data
+    according to a format string.
+    Note: this field has been originally implemented as an Adapter, but it 
+    was made a construct for performance reasons.
+    
+    Parameters:
+    * name - the name
+    * endianity - "<" for little endian, ">" for big endian, or "=" for native
+    * format - a single format character
+    
+    Example:
+    FormatField("foo", ">", "L")
+    """
+    __slots__ = ["packer"]
+    def __init__(self, name, endianity, format):
+        if endianity not in (">", "<", "="):
+            raise ValueError("endianity must be be '=', '<', or '>'", 
+                endianity)
+        if len(format) != 1:
+            raise ValueError("must specify one and only one format char")
+        self.packer = Packer(endianity + format)
+        StaticField.__init__(self, name, self.packer.size)
+    def __getstate__(self):
+        attrs = StaticField.__getstate__(self)
+        attrs["packer"] = attrs["packer"].format
+        return attrs
+    def __setstate__(self, attrs):
+        attrs["packer"] = Packer(attrs["packer"])
+        return StaticField.__setstate__(attrs)
+    def _parse(self, stream, context):
+        try:
+            return self.packer.unpack(_read_stream(stream, self.length))[0]
+        except Exception, ex:
+            raise FieldError(ex)
+    def _build(self, obj, stream, context):
+        try:
+            _write_stream(stream, self.length, self.packer.pack(obj))
+        except Exception, ex:
+            raise FieldError(ex)
+
+class MetaField(Construct):
+    """
+    A field of a meta-length. The length is computed at runtime based on
+    the context.
+    
+    Parameters:
+    * name - the name of the field
+    * lengthfunc - a function that takes the context as a parameter and return
+      the length of the field
+    
+    Example:
+    MetaField("foo", lambda ctx: 5)
+    """
+    __slots__ = ["lengthfunc"]
+    def __init__(self, name, lengthfunc):
+        Construct.__init__(self, name)
+        self.lengthfunc = lengthfunc
+        self._set_flag(self.FLAG_DYNAMIC)
+    def _parse(self, stream, context):
+        return _read_stream(stream, self.lengthfunc(context))
+    def _build(self, obj, stream, context):
+        _write_stream(stream, self.lengthfunc(context), obj)
+    def _sizeof(self, context):
+        return self.lengthfunc(context)
+
+
+#===============================================================================
+# arrays and repeaters
+#===============================================================================
+class MetaArray(Subconstruct):
+    """
+    An array (repeater) of a meta-count. The array will iterate exactly 
+    `countfunc()` times. Will raise ArrayError if less elements are found.
+    See also Array, Range and RepeatUntil.
+    
+    Parameters:
+    * countfunc - a function that takes the context as a parameter and returns
+      the number of elements of the array (count)
+    * subcon - the subcon to repeat `countfunc()` times
+    
+    Example:
+    MetaArray(lambda ctx: 5, UBInt8("foo"))
+    """
+    __slots__ = ["countfunc"]
+    def __init__(self, countfunc, subcon):
+        Subconstruct.__init__(self, subcon)
+        self.countfunc = countfunc
+        self._clear_flag(self.FLAG_COPY_CONTEXT)
+        self._set_flag(self.FLAG_DYNAMIC)
+    def _parse(self, stream, context):
+        obj = ListContainer()
+        c = 0
+        count = self.countfunc(context)
+        try:
+            if self.subcon.conflags & self.FLAG_COPY_CONTEXT:
+                while c < count:
+                    obj.append(self.subcon._parse(stream, context.__copy__()))
+                    c += 1
+            else:
+                while c < count:
+                    obj.append(self.subcon._parse(stream, context))
+                    c += 1
+        except ConstructError, ex:
+            raise ArrayError("expected %d, found %d" % (count, c), ex)
+        return obj
+    def _build(self, obj, stream, context):
+        count = self.countfunc(context)
+        if len(obj) != count:
+            raise ArrayError("expected %d, found %d" % (count, len(obj)))
+        if self.subcon.conflags & self.FLAG_COPY_CONTEXT:
+            for subobj in obj:
+                self.subcon._build(subobj, stream, context.__copy__())
+        else:
+            for subobj in obj:
+                self.subcon._build(subobj, stream, context)
+    def _sizeof(self, context):
+        return self.subcon._sizeof(context) * self.countfunc(context)
+
+class Range(Subconstruct):
+    """
+    A range-array. The subcon will iterate between `mincount` to `maxcount`
+    times. If less than `mincount` elements are found, raises RangeError.
+    See also GreedyRange and OptionalGreedyRange.
+    
+    Notes:
+    * requires a seekable stream.
+    
+    Parameters:
+    * mincount - the minimal count (an integer)
+    * maxcount - the maximal count (an integer)
+    * subcon - the subcon to repeat
+    
+    Example:
+    Range(5, 8, UBInt8("foo"))
+    """
+    __slots__ = ["mincount", "maxcout"]
+    def __init__(self, mincount, maxcout, subcon):
+        Subconstruct.__init__(self, subcon)
+        self.mincount = mincount
+        self.maxcout = maxcout
+        self._clear_flag(self.FLAG_COPY_CONTEXT)
+        self._set_flag(self.FLAG_DYNAMIC)
+    def _parse(self, stream, context):
+        obj = ListContainer()
+        c = 0
+        try:
+            if self.subcon.conflags & self.FLAG_COPY_CONTEXT:
+                while c < self.maxcout:
+                    pos = stream.tell()
+                    obj.append(self.subcon._parse(stream, context.__copy__()))
+                    c += 1
+            else:
+                while c < self.maxcout:
+                    pos = stream.tell()
+                    obj.append(self.subcon._parse(stream, context))
+                    c += 1
+        except ConstructError:
+            if c < self.mincount:
+                raise RangeError("expected %d to %d, found %d" % 
+                    (self.mincount, self.maxcout, c))
+            stream.seek(pos)
+        return obj
+    def _build(self, obj, stream, context):
+        if len(obj) < self.mincount or len(obj) > self.maxcout:
+            raise RangeError("expected %d to %d, found %d" % 
+                (self.mincount, self.maxcout, len(obj)))
+        cnt = 0
+        try:
+            if self.subcon.conflags & self.FLAG_COPY_CONTEXT:
+                for subobj in obj:
+                    self.subcon._build(subobj, stream, context.__copy__())
+                    cnt += 1
+            else:
+                for subobj in obj:
+                    self.subcon._build(subobj, stream, context)
+                    cnt += 1
+        except ConstructError:
+            if cnt < self.mincount:
+                raise RangeError("expected %d to %d, found %d" % 
+                    (self.mincount, self.maxcout, len(obj)))
+    def _sizeof(self, context):
+        raise SizeofError("can't calculate size")
+
+class RepeatUntil(Subconstruct):
+    """
+    An array that repeat until the predicate indicates it to stop. Note that
+    the last element (which caused the repeat to exit) is included in the 
+    return value.
+    
+    Parameters:
+    * predicate - a predicate function that takes (obj, context) and returns
+      True if the stop-condition is met, or False to continue.
+    * subcon - the subcon to repeat.
+    
+    Example:
+    # will read chars until \x00 (inclusive)
+    RepeatUntil(lambda obj, ctx: obj == "\x00",
+        Field("chars", 1)
+    )
+    """
+    __slots__ = ["predicate"]
+    def __init__(self, predicate, subcon):
+        Subconstruct.__init__(self, subcon)
+        self.predicate = predicate
+        self._clear_flag(self.FLAG_COPY_CONTEXT)
+        self._set_flag(self.FLAG_DYNAMIC)
+    def _parse(self, stream, context):
+        obj = []
+        try:
+            if self.subcon.conflags & self.FLAG_COPY_CONTEXT:
+                while True:
+                    subobj = self.subcon._parse(stream, context.__copy__())
+                    obj.append(subobj)
+                    if self.predicate(subobj, context):
+                        break
+            else:
+                while True:
+                    subobj = self.subcon._parse(stream, context)
+                    obj.append(subobj)
+                    if self.predicate(subobj, context):
+                        break
+        except ConstructError, ex:
+            raise ArrayError("missing terminator", ex)
+        return obj
+    def _build(self, obj, stream, context):
+        terminated = False
+        if self.subcon.conflags & self.FLAG_COPY_CONTEXT:
+            for subobj in obj:
+                self.subcon._build(subobj, stream, context.__copy__())
+                if self.predicate(subobj, context):
+                    terminated = True
+                    break
+        else:
+            for subobj in obj:
+                self.subcon._build(subobj, stream, context.__copy__())
+                if self.predicate(subobj, context):
+                    terminated = True
+                    break
+        if not terminated:
+            raise ArrayError("missing terminator")
+    def _sizeof(self, context):
+        raise SizeofError("can't calculate size")
+
+
+#===============================================================================
+# structures and sequences
+#===============================================================================
+class Struct(Construct):
+    """
+    A sequence of named constructs, similar to structs in C. The elements are
+    parsed and built in the order they are defined.
+    See also Embedded.
+    
+    Parameters:
+    * name - the name of the structure
+    * subcons - a sequence of subconstructs that make up this structure.
+    * nested - a keyword-only argument that indicates whether this struct 
+      creates a nested context. The default is True. This parameter is 
+      considered "advanced usage", and may be removed in the future.
+    
+    Example:
+    Struct("foo",
+        UBInt8("first_element"),
+        UBInt16("second_element"),
+        Padding(2),
+        UBInt8("third_element"),
+    )
+    """
+    __slots__ = ["subcons", "nested"]
+    def __init__(self, name, *subcons, **kw):
+        self.nested = kw.pop("nested", True)
+        if kw:
+            raise TypeError("the only keyword argument accepted is 'nested'", kw)
+        Construct.__init__(self, name)
+        self.subcons = subcons
+        self._inherit_flags(*subcons)
+        self._clear_flag(self.FLAG_EMBED)
+    def _parse(self, stream, context):
+        if "<obj>" in context:
+            obj = context["<obj>"]
+            del context["<obj>"]
+        else:
+            obj = Container()
+            if self.nested:
+                context = AttrDict(_ = context)
+        for sc in self.subcons:
+            if sc.conflags & self.FLAG_EMBED:
+                context["<obj>"] = obj
+                sc._parse(stream, context)
+            else:
+                subobj = sc._parse(stream, context)
+                if sc.name is not None:
+                    obj[sc.name] = subobj
+                    context[sc.name] = subobj
+        return obj
+    def _build(self, obj, stream, context):
+        if "<unnested>" in context:
+            del context["<unnested>"]
+        elif self.nested:
+            context = AttrDict(_ = context)
+        for sc in self.subcons:
+            if sc.conflags & self.FLAG_EMBED:
+                context["<unnested>"] = True
+                subobj = obj
+            elif sc.name is None:
+                subobj = None
+            else:
+                subobj = getattr(obj, sc.name)
+                context[sc.name] = subobj
+            sc._build(subobj, stream, context)
+    def _sizeof(self, context):
+        if self.nested:
+            context = AttrDict(_ = context)
+        return sum(sc._sizeof(context) for sc in self.subcons)
+
+class Sequence(Struct):
+    """
+    A sequence of unnamed constructs. The elements are parsed and built in the
+    order they are defined.
+    See also Embedded.
+    
+    Parameters:
+    * name - the name of the structure
+    * subcons - a sequence of subconstructs that make up this structure.
+    * nested - a keyword-only argument that indicates whether this struct 
+      creates a nested context. The default is True. This parameter is 
+      considered "advanced usage", and may be removed in the future.
+    
+    Example:
+    Sequence("foo",
+        UBInt8("first_element"),
+        UBInt16("second_element"),
+        Padding(2),
+        UBInt8("third_element"),
+    )
+    """
+    __slots__ = []
+    def _parse(self, stream, context):
+        if "<obj>" in context:
+            obj = context["<obj>"]
+            del context["<obj>"]
+        else:
+            obj = ListContainer()
+            if self.nested:
+                context = AttrDict(_ = context)
+        for sc in self.subcons:
+            if sc.conflags & self.FLAG_EMBED:
+                context["<obj>"] = obj
+                sc._parse(stream, context)
+            else:
+                subobj = sc._parse(stream, context)
+                if sc.name is not None:
+                    obj.append(subobj)
+                    context[sc.name] = subobj
+        return obj
+    def _build(self, obj, stream, context):
+        if "<unnested>" in context:
+            del context["<unnested>"]
+        elif self.nested:
+            context = AttrDict(_ = context)
+        objiter = iter(obj)
+        for sc in self.subcons:
+            if sc.conflags & self.FLAG_EMBED:
+                context["<unnested>"] = True
+                subobj = objiter
+            elif sc.name is None:
+                subobj = None
+            else:
+                subobj = objiter.next()
+                context[sc.name] = subobj
+            sc._build(subobj, stream, context)
+
+class Union(Construct):
+    """
+    a set of overlapping fields (like unions in C). when parsing, 
+    all fields read the same data; when building, only the first subcon
+    (called "master") is used. 
+    
+    Parameters:
+    * name - the name of the union
+    * master - the master subcon, i.e., the subcon used for building and 
+      calculating the total size
+    * subcons - additional subcons
+    
+    Example:
+    Union("what_are_four_bytes",
+        UBInt32("one_dword"),
+        Struct("two_words", UBInt16("first"), UBInt16("second")),
+        Struct("four_bytes", 
+            UBInt8("a"), 
+            UBInt8("b"), 
+            UBInt8("c"), 
+            UBInt8("d")
+        ),
+    )
+    """
+    __slots__ = ["parser", "builder"]
+    def __init__(self, name, master, *subcons, **kw):
+        Construct.__init__(self, name)
+        args = [Peek(sc) for sc in subcons]
+        args.append(MetaField(None, lambda ctx: master._sizeof(ctx)))
+        self.parser = Struct(name, Peek(master, perform_build = True), *args)
+        self.builder = Struct(name, master)
+    def _parse(self, stream, context):
+        return self.parser._parse(stream, context)
+    def _build(self, obj, stream, context):
+        return self.builder._build(obj, stream, context)
+    def _sizeof(self, context):
+        return self.builder._sizeof(context)
+
+#===============================================================================
+# conditional
+#===============================================================================
+class Switch(Construct):
+    """
+    A conditional branch. Switch will choose the case to follow based on
+    the return value of keyfunc. If no case is matched, and no default value 
+    is given, SwitchError will be raised.
+    See also Pass.
+    
+    Parameters:
+    * name - the name of the construct
+    * keyfunc - a function that takes the context and returns a key, which 
+      will ne used to choose the relevant case.
+    * cases - a dictionary mapping keys to constructs. the keys can be any 
+      values that may be returned by keyfunc.
+    * default - a default value to use when the key is not found in the cases.
+      if not supplied, an exception will be raised when the key is not found.
+      You can use the builtin construct Pass for 'do-nothing'.
+    * include_key - whether or not to include the key in the return value
+      of parsing. defualt is False.
+    
+    Example:
+    Struct("foo",
+        UBInt8("type"),
+        Switch("value", lambda ctx: ctx.type, {
+                1 : UBInt8("spam"),
+                2 : UBInt16("spam"),
+                3 : UBInt32("spam"),
+                4 : UBInt64("spam"),
+            }
+        ),
+    )
+    """
+    
+    class NoDefault(Construct):
+        def _parse(self, stream, context):
+            raise SwitchError("no default case defined")
+        def _build(self, obj, stream, context):
+            raise SwitchError("no default case defined")
+        def _sizeof(self, context):
+            raise SwitchError("no default case defined")
+    NoDefault = NoDefault("NoDefault")
+    
+    __slots__ = ["subcons", "keyfunc", "cases", "default", "include_key"]
+    
+    def __init__(self, name, keyfunc, cases, default = NoDefault, 
+                 include_key = False):
+        Construct.__init__(self, name)
+        self._inherit_flags(*cases.values())
+        self.keyfunc = keyfunc
+        self.cases = cases
+        self.default = default
+        self.include_key = include_key
+        self._inherit_flags(*cases.values())
+        self._set_flag(self.FLAG_DYNAMIC)
+    def _parse(self, stream, context):
+        key = self.keyfunc(context)
+        obj = self.cases.get(key, self.default)._parse(stream, context)
+        if self.include_key:
+            return key, obj
+        else:
+            return obj
+    def _build(self, obj, stream, context):
+        if self.include_key:
+            key, obj = obj
+        else:
+            key = self.keyfunc(context)
+        case = self.cases.get(key, self.default)
+        case._build(obj, stream, context)
+    def _sizeof(self, context):
+        case = self.cases.get(self.keyfunc(context), self.default)
+        return case._sizeof(context)
+
+class Select(Construct):
+    """
+    Selects the first matching subconstruct. It will literally try each of
+    the subconstructs, until one matches.
+    
+    Notes:
+    * requires a seekable stream.
+    
+    Parameters:
+    * name - the name of the construct
+    * subcons - the subcons to try (order-sensitive)
+    * include_name - a keyword only argument, indicating whether to include 
+      the name of the selected subcon in the return value of parsing. default
+      is false.
+    
+    Example:
+    Select("foo",
+        UBInt64("large"),
+        UBInt32("medium"),
+        UBInt16("small"),
+        UBInt8("tiny"),
+    )
+    """
+    __slots__ = ["subcons", "include_name"]
+    def __init__(self, name, *subcons, **kw):
+        include_name = kw.pop("include_name", False)
+        if kw:
+            raise TypeError("the only keyword argument accepted "
+                "is 'include_name'", kw)
+        Construct.__init__(self, name)
+        self.subcons = subcons
+        self.include_name = include_name
+        self._inherit_flags(*subcons)
+        self._set_flag(self.FLAG_DYNAMIC)
+    def _parse(self, stream, context):
+        for sc in self.subcons:
+            pos = stream.tell()
+            context2 = context.__copy__()
+            try:
+                obj = sc._parse(stream, context2)
+            except ConstructError:
+                stream.seek(pos)
+            else:
+                context.__update__(context2)
+                if self.include_name:
+                    return sc.name, obj
+                else:
+                    return obj
+        raise SelectError("no subconstruct matched")
+    def _build(self, obj, stream, context):
+        if self.include_name:
+            name, obj = obj
+            for sc in self.subcons:
+                if sc.name == name:
+                    sc._build(obj, stream, context)
+                    return
+        else: 
+            for sc in self.subcons:
+                stream2 = StringIO()
+                context2 = context.__copy__()
+                try:
+                    sc._build(obj, stream2, context2)
+                except Exception:
+                    pass
+                else:
+                    context.__update__(context2)
+                    stream.write(stream2.getvalue())
+                    return
+        raise SelectError("no subconstruct matched", obj)
+    def _sizeof(self, context):
+        raise SizeofError("can't calculate size")
+
+
+#===============================================================================
+# stream manipulation
+#===============================================================================
+class Pointer(Subconstruct):
+    """
+    Changes the stream position to a given offset, where the construction
+    should take place, and restores the stream position when finished.
+    See also Anchor, OnDemand and OnDemandPointer.
+    
+    Notes:
+    * requires a seekable stream.
+    
+    Parameters:
+    * offsetfunc: a function that takes the context and returns an absolute 
+      stream position, where the construction would take place
+    * subcon - the subcon to use at `offsetfunc()`
+    
+    Example:
+    Struct("foo",
+        UBInt32("spam_pointer"),
+        Pointer(lambda ctx: ctx.spam_pointer,
+            Array(5, UBInt8("spam"))
+        )
+    )
+    """
+    __slots__ = ["offsetfunc"]
+    def __init__(self, offsetfunc, subcon):
+        Subconstruct.__init__(self, subcon)
+        self.offsetfunc = offsetfunc
+    def _parse(self, stream, context):
+        newpos = self.offsetfunc(context)
+        origpos = stream.tell()
+        stream.seek(newpos)
+        obj = self.subcon._parse(stream, context)
+        stream.seek(origpos)
+        return obj
+    def _build(self, obj, stream, context):
+        newpos = self.offsetfunc(context)
+        origpos = stream.tell()
+        stream.seek(newpos)
+        self.subcon._build(obj, stream, context)
+        stream.seek(origpos)
+    def _sizeof(self, context):
+        return 0
+
+class Peek(Subconstruct):
+    """
+    Peeks at the stream: parses without changing the stream position.
+    See also Union. If the end of the stream is reached when peeking,
+    returns None.
+    
+    Notes:
+    * requires a seekable stream.
+    
+    Parameters:
+    * subcon - the subcon to peek at
+    * perform_build - whether or not to perform building. by default this 
+      parameter is set to False, meaning building is a no-op.
+    
+    Example:
+    Peek(UBInt8("foo"))
+    """
+    __slots__ = ["perform_build"]
+    def __init__(self, subcon, perform_build = False):
+        Subconstruct.__init__(self, subcon)
+        self.perform_build = perform_build
+    def _parse(self, stream, context):
+        pos = stream.tell()
+        try:
+            try:
+                return self.subcon._parse(stream, context)
+            except FieldError:
+                pass
+        finally:
+            stream.seek(pos)
+    def _build(self, obj, stream, context):
+        if self.perform_build:
+            self.subcon._build(obj, stream, context)
+    def _sizeof(self, context):
+        return 0
+
+class OnDemand(Subconstruct):
+    """
+    Allows for on-demand (lazy) parsing. When parsing, it will return a 
+    LazyContainer that represents a pointer to the data, but does not actually
+    parses it from stream until it's "demanded".
+    By accessing the 'value' property of LazyContainers, you will demand the 
+    data from the stream. The data will be parsed and cached for later use.
+    You can use the 'has_value' property to know whether the data has already 
+    been demanded.
+    See also OnDemandPointer.
+    
+    Notes:
+    * requires a seekable stream.
+    
+    Parameters:
+    * subcon - 
+    * advance_stream - whether or not to advance the stream position. by 
+      default this is True, but if subcon is a pointer, this should be False.
+    * force_build - whether or not to force build. If set to False, and the
+      LazyContainer has not been demaned, building is a no-op.
+    
+    Example:
+    OnDemand(Array(10000, UBInt8("foo"))
+    """
+    __slots__ = ["advance_stream", "force_build"]
+    def __init__(self, subcon, advance_stream = True, force_build = True):
+        Subconstruct.__init__(self, subcon)
+        self.advance_stream = advance_stream
+        self.force_build = force_build
+    def _parse(self, stream, context):
+        obj = LazyContainer(self.subcon, stream, stream.tell(), context)
+        if self.advance_stream:
+            stream.seek(self.subcon._sizeof(context), 1)
+        return obj
+    def _build(self, obj, stream, context):
+        if not isinstance(obj, LazyContainer):
+            self.subcon._build(obj, stream, context)
+        elif self.force_build or obj.has_value:
+            self.subcon._build(obj.value, stream, context)
+        elif self.advance_stream:
+            stream.seek(self.subcon._sizeof(context), 1)
+
+class Buffered(Subconstruct):
+    """
+    Creates an in-memory buffered stream, which can undergo encoding and 
+    decoding prior to being passed on to the subconstruct.
+    See also Bitwise.
+    
+    Note:
+    * Do not use pointers inside Buffered
+    
+    Parameters:
+    * subcon - the subcon which will operate on the buffer
+    * encoder - a function that takes a string and returns an encoded
+      string (used after building)
+    * decoder - a function that takes a string and returns a decoded
+      string (used before parsing)
+    * resizer - a function that takes the size of the subcon and "adjusts"
+      or "resizes" it according to the encoding/decoding process.
+    
+    Example:
+    Buffered(BitField("foo", 16),
+        encoder = decode_bin,
+        decoder = encode_bin,
+        resizer = lambda size: size / 8,
+    )
+    """
+    __slots__ = ["encoder", "decoder", "resizer"]
+    def __init__(self, subcon, decoder, encoder, resizer):
+        Subconstruct.__init__(self, subcon)
+        self.encoder = encoder
+        self.decoder = decoder
+        self.resizer = resizer
+    def _parse(self, stream, context):
+        data = _read_stream(stream, self._sizeof(context))
+        stream2 = StringIO(self.decoder(data))
+        return self.subcon._parse(stream2, context)
+    def _build(self, obj, stream, context):
+        size = self._sizeof(context)
+        stream2 = StringIO()
+        self.subcon._build(obj, stream2, context)
+        data = self.encoder(stream2.getvalue())
+        assert len(data) == size
+        _write_stream(stream, self._sizeof(context), data)
+    def _sizeof(self, context):
+        return self.resizer(self.subcon._sizeof(context))
+
+class Restream(Subconstruct):
+    """
+    Wraps the stream with a read-wrapper (for parsing) or a 
+    write-wrapper (for building). The stream wrapper can buffer the data
+    internally, reading it from- or writing it to the underlying stream 
+    as needed. For example, BitStreamReader reads whole bytes from the 
+    underlying stream, but returns them as individual bits. 
+    See also Bitwise.
+    
+    When the parsing or building is done, the stream's close method 
+    will be invoked. It can perform any finalization needed for the stream
+    wrapper, but it must not close the underlying stream.
+    
+    Note:
+    * Do not use pointers inside Restream
+    
+    Parameters:
+    * subcon - the subcon
+    * stream_reader - the read-wrapper
+    * stream_writer - the write wrapper
+    * resizer - a function that takes the size of the subcon and "adjusts"
+      or "resizes" it according to the encoding/decoding process.
+    
+    Example:
+    Restream(BitField("foo", 16),
+        stream_reader = BitStreamReader,
+        stream_writer = BitStreamWriter,
+        resizer = lambda size: size / 8,
+    )
+    """
+    __slots__ = ["stream_reader", "stream_writer", "resizer"]
+    def __init__(self, subcon, stream_reader, stream_writer, resizer):
+        Subconstruct.__init__(self, subcon)
+        self.stream_reader = stream_reader
+        self.stream_writer = stream_writer
+        self.resizer = resizer
+    def _parse(self, stream, context):
+        stream2 = self.stream_reader(stream)
+        obj = self.subcon._parse(stream2, context)
+        stream2.close()
+        return obj
+    def _build(self, obj, stream, context):
+        stream2 = self.stream_writer(stream)
+        self.subcon._build(obj, stream2, context)
+        stream2.close()
+    def _sizeof(self, context):
+        return self.resizer(self.subcon._sizeof(context))
+
+
+#===============================================================================
+# miscellaneous
+#===============================================================================
+class Reconfig(Subconstruct):
+    """
+    Reconfigures a subconstruct. Reconfig can be used to change the name and
+    set and clear flags of the inner subcon.
+    
+    Parameters:
+    * name - the new name
+    * subcon - the subcon to reconfigure
+    * setflags - the flags to set (default is 0)
+    * clearflags - the flags to clear (default is 0)
+    
+    Example:
+    Reconfig("foo", UBInt8("bar"))
+    """
+    __slots__ = []
+    def __init__(self, name, subcon, setflags = 0, clearflags = 0):
+        Construct.__init__(self, name, subcon.conflags)
+        self.subcon = subcon
+        self._set_flag(setflags)
+        self._clear_flag(clearflags)
+
+class Anchor(Construct):
+    """
+    Returns the "anchor" (stream position) at the point where it's inserted.
+    Useful for adjusting relative offsets to absolute positions, or to measure
+    sizes of constructs.
+    absolute pointer = anchor + relative offset
+    size = anchor_after - anchor_before
+    See also Pointer.
+    
+    Notes:
+    * requires a seekable stream.
+    
+    Parameters:
+    * name - the name of the anchor
+    
+    Example:
+    Struct("foo",
+        Anchor("base"),
+        UBInt8("relative_offset"),
+        Pointer(lambda ctx: ctx.relative_offset + ctx.base,
+            UBInt8("data")
+        )
+    )
+    """
+    __slots__ = []
+    def _parse(self, stream, context):
+        return stream.tell()
+    def _build(self, obj, stream, context):
+        context[self.name] = stream.tell()
+    def _sizeof(self, context):
+        return 0
+
+class Value(Construct):
+    """
+    A computed value.
+    
+    Parameters:
+    * name - the name of the value
+    * func - a function that takes the context and return the computed value
+    
+    Example:
+    Struct("foo",
+        UBInt8("width"),
+        UBInt8("height"),
+        Value("total_pixels", lambda ctx: ctx.width * ctx.height),
+    )
+    """
+    __slots__ = ["func"]
+    def __init__(self, name, func):
+        Construct.__init__(self, name)
+        self.func = func
+        self._set_flag(self.FLAG_DYNAMIC)
+    def _parse(self, stream, context):
+        return self.func(context)
+    def _build(self, obj, stream, context):
+        context[self.name] = self.func(context)
+    def _sizeof(self, context):
+        return 0
+
+#class Dynamic(Construct):
+#    """
+#    Dynamically creates a construct and uses it for parsing and building.
+#    This allows you to create change the construction tree on the fly.
+#    Deprecated.
+#    
+#    Parameters:
+#    * name - the name of the construct
+#    * factoryfunc - a function that takes the context and returns a new 
+#      construct object which will be used for parsing and building.
+#    
+#    Example:
+#    def factory(ctx):
+#        if ctx.bar == 8:
+#            return UBInt8("spam")
+#        if ctx.bar == 9:
+#            return String("spam", 9)
+#    
+#    Struct("foo",
+#        UBInt8("bar"),
+#        Dynamic("spam", factory),
+#    )
+#    """
+#    __slots__ = ["factoryfunc"]
+#    def __init__(self, name, factoryfunc):
+#        Construct.__init__(self, name, self.FLAG_COPY_CONTEXT)
+#        self.factoryfunc = factoryfunc
+#        self._set_flag(self.FLAG_DYNAMIC)
+#    def _parse(self, stream, context):
+#        return self.factoryfunc(context)._parse(stream, context)
+#    def _build(self, obj, stream, context):
+#        return self.factoryfunc(context)._build(obj, stream, context)
+#    def _sizeof(self, context):
+#        return self.factoryfunc(context)._sizeof(context)
+
+class LazyBound(Construct):
+    """
+    Lazily bound construct, useful for constructs that need to make cyclic 
+    references (linked-lists, expression trees, etc.).
+    
+    Parameters:
+    
+    
+    Example:
+    foo = Struct("foo",
+        UBInt8("bar"),
+        LazyBound("next", lambda: foo),
+    )
+    """
+    __slots__ = ["bindfunc", "bound"]
+    def __init__(self, name, bindfunc):
+        Construct.__init__(self, name)
+        self.bound = None
+        self.bindfunc = bindfunc
+    def _parse(self, stream, context):
+        if self.bound is None:
+            self.bound = self.bindfunc()
+        return self.bound._parse(stream, context)
+    def _build(self, obj, stream, context):
+        if self.bound is None:
+            self.bound = self.bindfunc()
+        self.bound._build(obj, stream, context)
+    def _sizeof(self, context):
+        if self.bound is None:
+            self.bound = self.bindfunc()
+        return self.bound._sizeof(context)
+
+class Pass(Construct):
+    """
+    A do-nothing construct, useful as the default case for Switch, or
+    to indicate Enums.
+    See also Switch and Enum.
+    
+    Notes:
+    * this construct is a singleton. do not try to instatiate it, as it 
+      will not work :)
+    
+    Example:
+    Pass
+    """
+    __slots__ = []
+    def _parse(self, stream, context):
+        pass
+    def _build(self, obj, stream, context):
+        assert obj is None
+    def _sizeof(self, context):
+        return 0
+Pass = Pass(None)
+
+class Terminator(Construct):
+    """
+    Asserts the end of the stream has been reached at the point it's placed.
+    You can use this to ensure no more unparsed data follows.
+    
+    Notes:
+    * this construct is a singleton. do not try to instatiate it, as it 
+      will not work :)
+    
+    Example:
+    Terminator
+    """
+    __slots__ = []
+    def _parse(self, stream, context):
+        if stream.read(1):
+            raise TerminatorError("expected end of stream")
+    def _build(self, obj, stream, context):
+        assert obj is None
+    def _sizeof(self, context):
+        return 0
+Terminator = Terminator(None)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/elftools/construct/debug.py b/elftools/construct/debug.py
index 47e47c6..b2df465 100644
--- a/elftools/construct/debug.py
+++ b/elftools/construct/debug.py
@@ -1,160 +1,160 @@
-"""

-Debugging utilities for constructs

-"""

-import sys

-import traceback

-import pdb

-import inspect

-from core import Construct, Subconstruct

-from lib import HexString, Container, ListContainer, AttrDict

-

-

-class Probe(Construct):

-    """

-    A probe: dumps the context, stack frames, and stream content to the screen

-    to aid the debugging process.

-    See also Debugger.

-    

-    Parameters:

-    * name - the display name

-    * show_stream - whether or not to show stream contents. default is True. 

-      the stream must be seekable.

-    * show_context - whether or not to show the context. default is True.

-    * show_stack - whether or not to show the upper stack frames. default 

-      is True.

-    * stream_lookahead - the number of bytes to dump when show_stack is set.

-      default is 100.

-    

-    Example:

-    Struct("foo",

-        UBInt8("a"),

-        Probe("between a and b"),

-        UBInt8("b"),

-    )

-    """

-    __slots__ = [

-        "printname", "show_stream", "show_context", "show_stack", 

-        "stream_lookahead"

-    ]

-    counter = 0

-    

-    def __init__(self, name = None, show_stream = True, 

-                 show_context = True, show_stack = True, 

-                 stream_lookahead = 100):

-        Construct.__init__(self, None)

-        if name is None:

-            Probe.counter += 1

-            name = "<unnamed %d>" % (Probe.counter,)

-        self.printname = name

-        self.show_stream = show_stream

-        self.show_context = show_context

-        self.show_stack = show_stack

-        self.stream_lookahead = stream_lookahead

-    def __repr__(self):

-        return "%s(%r)" % (self.__class__.__name__, self.printname)

-    def _parse(self, stream, context):

-        self.printout(stream, context)

-    def _build(self, obj, stream, context):

-        self.printout(stream, context)

-    def _sizeof(self, context):

-        return 0

-    

-    def printout(self, stream, context):

-        obj = Container()

-        if self.show_stream:

-            obj.stream_position = stream.tell()

-            follows = stream.read(self.stream_lookahead)

-            if not follows:

-                obj.following_stream_data = "EOF reached"

-            else:

-                stream.seek(-len(follows), 1)

-                obj.following_stream_data = HexString(follows)

-            print

-        

-        if self.show_context:

-            obj.context = context

-        

-        if self.show_stack:

-            obj.stack = ListContainer()

-            frames = [s[0] for s in inspect.stack()][1:-1]

-            frames.reverse()

-            for f in frames:

-                a = AttrDict()

-                a.__update__(f.f_locals)

-                obj.stack.append(a)

-        

-        print "=" * 80

-        print "Probe", self.printname

-        print obj

-        print "=" * 80

-

-class Debugger(Subconstruct):

-    """

-    A pdb-based debugger. When an exception occurs in the subcon, a debugger

-    will appear and allow you to debug the error (and even fix on-the-fly).

-    

-    Parameters:

-    * subcon - the subcon to debug

-    

-    Example:

-    Debugger(

-        Enum(UBInt8("foo"),

-            a = 1,

-            b = 2,

-            c = 3

-        )

-    )

-    """

-    __slots__ = ["retval"]

-    def _parse(self, stream, context):

-        try:

-            return self.subcon._parse(stream, context)

-        except Exception:

-            self.retval = NotImplemented

-            self.handle_exc("(you can set the value of 'self.retval', "

-                "which will be returned)")

-            if self.retval is NotImplemented:

-                raise

-            else:

-                return self.retval

-    def _build(self, obj, stream, context):

-        try:

-            self.subcon._build(obj, stream, context)

-        except Exception:

-            self.handle_exc()

-    def handle_exc(self, msg = None):

-        print "=" * 80

-        print "Debugging exception of %s:" % (self.subcon,)

-        print "".join(traceback.format_exception(*sys.exc_info())[1:])

-        if msg:

-            print msg

-        pdb.post_mortem(sys.exc_info()[2])

-        print "=" * 80

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

+"""
+Debugging utilities for constructs
+"""
+import sys
+import traceback
+import pdb
+import inspect
+from core import Construct, Subconstruct
+from lib import HexString, Container, ListContainer, AttrDict
+
+
+class Probe(Construct):
+    """
+    A probe: dumps the context, stack frames, and stream content to the screen
+    to aid the debugging process.
+    See also Debugger.
+    
+    Parameters:
+    * name - the display name
+    * show_stream - whether or not to show stream contents. default is True. 
+      the stream must be seekable.
+    * show_context - whether or not to show the context. default is True.
+    * show_stack - whether or not to show the upper stack frames. default 
+      is True.
+    * stream_lookahead - the number of bytes to dump when show_stack is set.
+      default is 100.
+    
+    Example:
+    Struct("foo",
+        UBInt8("a"),
+        Probe("between a and b"),
+        UBInt8("b"),
+    )
+    """
+    __slots__ = [
+        "printname", "show_stream", "show_context", "show_stack", 
+        "stream_lookahead"
+    ]
+    counter = 0
+    
+    def __init__(self, name = None, show_stream = True, 
+                 show_context = True, show_stack = True, 
+                 stream_lookahead = 100):
+        Construct.__init__(self, None)
+        if name is None:
+            Probe.counter += 1
+            name = "<unnamed %d>" % (Probe.counter,)
+        self.printname = name
+        self.show_stream = show_stream
+        self.show_context = show_context
+        self.show_stack = show_stack
+        self.stream_lookahead = stream_lookahead
+    def __repr__(self):
+        return "%s(%r)" % (self.__class__.__name__, self.printname)
+    def _parse(self, stream, context):
+        self.printout(stream, context)
+    def _build(self, obj, stream, context):
+        self.printout(stream, context)
+    def _sizeof(self, context):
+        return 0
+    
+    def printout(self, stream, context):
+        obj = Container()
+        if self.show_stream:
+            obj.stream_position = stream.tell()
+            follows = stream.read(self.stream_lookahead)
+            if not follows:
+                obj.following_stream_data = "EOF reached"
+            else:
+                stream.seek(-len(follows), 1)
+                obj.following_stream_data = HexString(follows)
+            print
+        
+        if self.show_context:
+            obj.context = context
+        
+        if self.show_stack:
+            obj.stack = ListContainer()
+            frames = [s[0] for s in inspect.stack()][1:-1]
+            frames.reverse()
+            for f in frames:
+                a = AttrDict()
+                a.__update__(f.f_locals)
+                obj.stack.append(a)
+        
+        print "=" * 80
+        print "Probe", self.printname
+        print obj
+        print "=" * 80
+
+class Debugger(Subconstruct):
+    """
+    A pdb-based debugger. When an exception occurs in the subcon, a debugger
+    will appear and allow you to debug the error (and even fix on-the-fly).
+    
+    Parameters:
+    * subcon - the subcon to debug
+    
+    Example:
+    Debugger(
+        Enum(UBInt8("foo"),
+            a = 1,
+            b = 2,
+            c = 3
+        )
+    )
+    """
+    __slots__ = ["retval"]
+    def _parse(self, stream, context):
+        try:
+            return self.subcon._parse(stream, context)
+        except Exception:
+            self.retval = NotImplemented
+            self.handle_exc("(you can set the value of 'self.retval', "
+                "which will be returned)")
+            if self.retval is NotImplemented:
+                raise
+            else:
+                return self.retval
+    def _build(self, obj, stream, context):
+        try:
+            self.subcon._build(obj, stream, context)
+        except Exception:
+            self.handle_exc()
+    def handle_exc(self, msg = None):
+        print "=" * 80
+        print "Debugging exception of %s:" % (self.subcon,)
+        print "".join(traceback.format_exception(*sys.exc_info())[1:])
+        if msg:
+            print msg
+        pdb.post_mortem(sys.exc_info()[2])
+        print "=" * 80
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/elftools/construct/lib/__init__.py b/elftools/construct/lib/__init__.py
index 23f0820..84d88db 100644
--- a/elftools/construct/lib/__init__.py
+++ b/elftools/construct/lib/__init__.py
@@ -1,10 +1,10 @@
-from binary import int_to_bin, bin_to_int, swap_bytes, encode_bin, decode_bin

-from bitstream import BitStreamReader, BitStreamWriter

-from container import (Container, AttrDict, FlagsContainer, 

-    ListContainer, LazyContainer)

-from hex import HexString, hexdump

-from utils import Packer, StringIO

-

-

-

-

+from binary import int_to_bin, bin_to_int, swap_bytes, encode_bin, decode_bin
+from bitstream import BitStreamReader, BitStreamWriter
+from container import (Container, AttrDict, FlagsContainer, 
+    ListContainer, LazyContainer)
+from hex import HexString, hexdump
+from utils import Packer, StringIO
+
+
+
+
diff --git a/elftools/construct/lib/binary.py b/elftools/construct/lib/binary.py
index 971882e..b348da2 100644
--- a/elftools/construct/lib/binary.py
+++ b/elftools/construct/lib/binary.py
@@ -1,61 +1,61 @@
-def int_to_bin(number, width = 32):

-    if number < 0:

-        number += 1 << width

-    i = width - 1

-    bits = ["\x00"] * width

-    while number and i >= 0:

-        bits[i] = "\x00\x01"[number & 1]

-        number >>= 1

-        i -= 1

-    return "".join(bits)

-

-_bit_values = {"\x00" : 0, "\x01" : 1, "0" : 0, "1" : 1}

-def bin_to_int(bits, signed = False):

-    number = 0

-    bias = 0

-    if signed and _bit_values[bits[0]] == 1:

-        bits = bits[1:]

-        bias = 1 << len(bits)

-    for b in bits:

-        number <<= 1

-        number |= _bit_values[b]

-    return number - bias

-

-def swap_bytes(bits, bytesize = 8):

-    i = 0

-    l = len(bits)

-    output = [""] * ((l // bytesize) + 1)

-    j = len(output) - 1

-    while i < l:

-        output[j] = bits[i : i + bytesize]

-        i += bytesize

-        j -= 1

-    return "".join(output)

-

-_char_to_bin = {}

-_bin_to_char = {}

-for i in range(256):

-    ch = chr(i)

-    bin = int_to_bin(i, 8)

-    _char_to_bin[ch] = bin

-    _bin_to_char[bin] = ch

-    _bin_to_char[bin] = ch

-

-def encode_bin(data):

-    return "".join(_char_to_bin[ch] for ch in data)

-

-def decode_bin(data):

-    assert len(data) & 7 == 0, "data length must be a multiple of 8"

-    i = 0

-    j = 0

-    l = len(data) // 8

-    chars = [""] * l

-    while j < l:

-        chars[j] = _bin_to_char[data[i:i+8]]

-        i += 8

-        j += 1

-    return "".join(chars)

-

-

-

-

+def int_to_bin(number, width = 32):
+    if number < 0:
+        number += 1 << width
+    i = width - 1
+    bits = ["\x00"] * width
+    while number and i >= 0:
+        bits[i] = "\x00\x01"[number & 1]
+        number >>= 1
+        i -= 1
+    return "".join(bits)
+
+_bit_values = {"\x00" : 0, "\x01" : 1, "0" : 0, "1" : 1}
+def bin_to_int(bits, signed = False):
+    number = 0
+    bias = 0
+    if signed and _bit_values[bits[0]] == 1:
+        bits = bits[1:]
+        bias = 1 << len(bits)
+    for b in bits:
+        number <<= 1
+        number |= _bit_values[b]
+    return number - bias
+
+def swap_bytes(bits, bytesize = 8):
+    i = 0
+    l = len(bits)
+    output = [""] * ((l // bytesize) + 1)
+    j = len(output) - 1
+    while i < l:
+        output[j] = bits[i : i + bytesize]
+        i += bytesize
+        j -= 1
+    return "".join(output)
+
+_char_to_bin = {}
+_bin_to_char = {}
+for i in range(256):
+    ch = chr(i)
+    bin = int_to_bin(i, 8)
+    _char_to_bin[ch] = bin
+    _bin_to_char[bin] = ch
+    _bin_to_char[bin] = ch
+
+def encode_bin(data):
+    return "".join(_char_to_bin[ch] for ch in data)
+
+def decode_bin(data):
+    assert len(data) & 7 == 0, "data length must be a multiple of 8"
+    i = 0
+    j = 0
+    l = len(data) // 8
+    chars = [""] * l
+    while j < l:
+        chars[j] = _bin_to_char[data[i:i+8]]
+        i += 8
+        j += 1
+    return "".join(chars)
+
+
+
+
diff --git a/elftools/construct/lib/bitstream.py b/elftools/construct/lib/bitstream.py
index ff56be6..e473864 100644
--- a/elftools/construct/lib/bitstream.py
+++ b/elftools/construct/lib/bitstream.py
@@ -1,80 +1,80 @@
-from binary import encode_bin, decode_bin

-

-

-class BitStreamReader(object):

-    __slots__ = ["substream", "buffer", "total_size"]

-    def __init__(self, substream):

-        self.substream = substream

-        self.total_size = 0

-        self.buffer = ""

-    def close(self):

-        if self.total_size % 8 != 0:

-            raise ValueError("total size of read data must be a multiple of 8",

-                self.total_size)

-    def tell(self):

-        return self.substream.tell()

-    def seek(self, pos, whence = 0):

-        self.buffer = ""

-        self.total_size = 0

-        self.substream.seek(pos, whence)

-    def read(self, count):

-        assert count >= 0

-        l = len(self.buffer)

-        if count == 0:

-            data = ""

-        elif count <= l:

-            data = self.buffer[:count]

-            self.buffer = self.buffer[count:]

-        else:

-            data = self.buffer

-            count -= l

-            bytes = count // 8

-            if count & 7: 

-                bytes += 1

-            buf = encode_bin(self.substream.read(bytes))

-            data += buf[:count]

-            self.buffer = buf[count:]

-        self.total_size += len(data)

-        return data

-

-

-class BitStreamWriter(object):

-    __slots__ = ["substream", "buffer", "pos"]

-    def __init__(self, substream):

-        self.substream = substream

-        self.buffer = []

-        self.pos = 0

-    def close(self):

-        self.flush()

-    def flush(self):

-        bytes = decode_bin("".join(self.buffer))

-        self.substream.write(bytes)

-        self.buffer = []

-        self.pos = 0

-    def tell(self):

-        return self.substream.tell() + self.pos // 8

-    def seek(self, pos, whence = 0):

-        self.flush()

-        self.substream.seek(pos, whence)

-    def write(self, data):

-        if not data:

-            return

-        if type(data) is not str:

-            raise TypeError("data must be a string, not %r" % (type(data),))

-        self.buffer.append(data)

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

+from binary import encode_bin, decode_bin
+
+
+class BitStreamReader(object):
+    __slots__ = ["substream", "buffer", "total_size"]
+    def __init__(self, substream):
+        self.substream = substream
+        self.total_size = 0
+        self.buffer = ""
+    def close(self):
+        if self.total_size % 8 != 0:
+            raise ValueError("total size of read data must be a multiple of 8",
+                self.total_size)
+    def tell(self):
+        return self.substream.tell()
+    def seek(self, pos, whence = 0):
+        self.buffer = ""
+        self.total_size = 0
+        self.substream.seek(pos, whence)
+    def read(self, count):
+        assert count >= 0
+        l = len(self.buffer)
+        if count == 0:
+            data = ""
+        elif count <= l:
+            data = self.buffer[:count]
+            self.buffer = self.buffer[count:]
+        else:
+            data = self.buffer
+            count -= l
+            bytes = count // 8
+            if count & 7: 
+                bytes += 1
+            buf = encode_bin(self.substream.read(bytes))
+            data += buf[:count]
+            self.buffer = buf[count:]
+        self.total_size += len(data)
+        return data
+
+
+class BitStreamWriter(object):
+    __slots__ = ["substream", "buffer", "pos"]
+    def __init__(self, substream):
+        self.substream = substream
+        self.buffer = []
+        self.pos = 0
+    def close(self):
+        self.flush()
+    def flush(self):
+        bytes = decode_bin("".join(self.buffer))
+        self.substream.write(bytes)
+        self.buffer = []
+        self.pos = 0
+    def tell(self):
+        return self.substream.tell() + self.pos // 8
+    def seek(self, pos, whence = 0):
+        self.flush()
+        self.substream.seek(pos, whence)
+    def write(self, data):
+        if not data:
+            return
+        if type(data) is not str:
+            raise TypeError("data must be a string, not %r" % (type(data),))
+        self.buffer.append(data)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/elftools/construct/lib/container.py b/elftools/construct/lib/container.py
index 66f8ab4..4b2f727 100644
--- a/elftools/construct/lib/container.py
+++ b/elftools/construct/lib/container.py
@@ -1,258 +1,258 @@
-def recursion_lock(retval, lock_name = "__recursion_lock__"):

-    def decorator(func):

-        def wrapper(self, *args, **kw):

-            if getattr(self, lock_name, False):

-                return retval

-            setattr(self, lock_name, True)

-            try:

-                return func(self, *args, **kw)

-            finally:

-                setattr(self, lock_name, False)

-        wrapper.__name__ = func.__name__

-        return wrapper

-    return decorator

-

-class Container(object):

-    """

-    A generic container of attributes

-    """

-    __slots__ = ["__dict__", "__attrs__"]

-    def __init__(self, **kw):

-        self.__dict__.update(kw)

-        object.__setattr__(self, "__attrs__", kw.keys())

-    

-    def __eq__(self, other):

-        try:

-            return self.__dict__ == other.__dict__

-        except AttributeError:

-            return False

-    def __ne__(self, other):

-        return not (self == other)

-    

-    def __delattr__(self, name):

-        object.__delattr__(self, name)

-        self.__attrs__.remove(name)

-    def __setattr__(self, name, value):

-        d = self.__dict__

-        if name not in d:

-            self.__attrs__.append(name)

-        d[name] = value

-    def __getitem__(self, name):

-        return self.__dict__[name]

-    def __delitem__(self, name):

-        self.__delattr__(name)

-    def __setitem__(self, name, value):

-        self.__setattr__(name, value)

-    def __update__(self, obj):

-        for name in obj.__attrs__:

-            self[name] = obj[name]

-    def __copy__(self):

-        new = self.__class__()

-        new.__attrs__ = self.__attrs__[:]

-        new.__dict__ = self.__dict__.copy()

-        return new

-    

-    @recursion_lock("<...>")

-    def __repr__(self):

-        attrs = sorted("%s = %r" % (k, v) 

-            for k, v in self.__dict__.iteritems() 

-            if not k.startswith("_"))

-        return "%s(%s)" % (self.__class__.__name__, ", ".join(attrs))

-    def __str__(self):

-        return self.__pretty_str__()

-    @recursion_lock("<...>")

-    def __pretty_str__(self, nesting = 1, indentation = "    "):

-        attrs = []

-        ind = indentation * nesting

-        for k in self.__attrs__:

-            v = self.__dict__[k]

-            if not k.startswith("_"):

-                text = [ind, k, " = "]

-                if hasattr(v, "__pretty_str__"):

-                    text.append(v.__pretty_str__(nesting + 1, indentation))

-                else:

-                    text.append(repr(v))

-                attrs.append("".join(text))

-        if not attrs:

-            return "%s()" % (self.__class__.__name__,)

-        attrs.insert(0, self.__class__.__name__ + ":")

-        return "\n".join(attrs)

-

-class FlagsContainer(Container):

-    """

-    A container providing pretty-printing for flags. Only set flags are 

-    displayed. 

-    """

-    def __pretty_str__(self, nesting = 1, indentation = "    "):

-        attrs = []

-        ind = indentation * nesting

-        for k in self.__attrs__:

-            v = self.__dict__[k]

-            if not k.startswith("_") and v:

-                attrs.append(ind + k)

-        if not attrs:

-            return "%s()" % (self.__class__.__name__,)

-        attrs.insert(0, self.__class__.__name__+ ":")

-        return "\n".join(attrs)

-

-class ListContainer(list):

-    """

-    A container for lists

-    """

-    __slots__ = ["__recursion_lock__"]

-    def __str__(self):

-        return self.__pretty_str__()

-    @recursion_lock("[...]")

-    def __pretty_str__(self, nesting = 1, indentation = "    "):

-        if not self:

-            return "[]"

-        ind = indentation * nesting

-        lines = ["["]

-        for elem in self:

-            lines.append("\n")

-            lines.append(ind)

-            if hasattr(elem, "__pretty_str__"):

-                lines.append(elem.__pretty_str__(nesting + 1, indentation))

-            else:

-                lines.append(repr(elem))

-        lines.append("\n")

-        lines.append(indentation * (nesting - 1))

-        lines.append("]")

-        return "".join(lines)

-

-class AttrDict(object):

-    """

-    A dictionary that can be accessed both using indexing and attributes,

-    i.e., 

-        x = AttrDict()

-        x.foo = 5

-        print x["foo"]

-    """

-    __slots__ = ["__dict__"]

-    def __init__(self, **kw):

-        self.__dict__ = kw

-    def __contains__(self, key):

-        return key in self.__dict__

-    def __nonzero__(self):

-        return bool(self.__dict__)

-    def __repr__(self):

-        return repr(self.__dict__)

-    def __str__(self):

-        return self.__pretty_str__()

-    def __pretty_str__(self, nesting = 1, indentation = "    "):

-        if not self:

-            return "{}"

-        text = ["{\n"]

-        ind = nesting * indentation

-        for k in sorted(self.__dict__.keys()):

-            v = self.__dict__[k]

-            text.append(ind)

-            text.append(repr(k))

-            text.append(" : ")

-            if hasattr(v, "__pretty_str__"):

-                try:

-                    text.append(v.__pretty_str__(nesting+1, indentation))

-                except Exception:

-                    text.append(repr(v))

-            else:

-                text.append(repr(v))

-            text.append("\n")

-        text.append((nesting-1) * indentation)

-        text.append("}")

-        return "".join(text)

-    def __delitem__(self, key):

-        del self.__dict__[key]

-    def __getitem__(self, key):

-        return self.__dict__[key]

-    def __setitem__(self, key, value):

-        self.__dict__[key] = value

-    def __copy__(self):

-        new = self.__class__()

-        new.__dict__ = self.__dict__.copy()

-        return new

-    def __update__(self, other):

-        if isinstance(other, dict):

-            self.__dict__.update(other)

-        else:

-            self.__dict__.update(other.__dict__)

-

-class LazyContainer(object):

-    __slots__ = ["subcon", "stream", "pos", "context", "_value"]

-    def __init__(self, subcon, stream, pos, context):

-        self.subcon = subcon

-        self.stream = stream

-        self.pos = pos

-        self.context = context

-        self._value = NotImplemented

-    def __eq__(self, other):

-        try:

-            return self._value == other._value

-        except AttributeError:

-            return False

-    def __ne__(self, other):

-        return not (self == other)

-    def __str__(self):

-        return self.__pretty_str__()

-    def __pretty_str__(self, nesting = 1, indentation = "    "):

-        if self._value is NotImplemented:

-            text = "<unread>"

-        elif hasattr(self._value, "__pretty_str__"):

-            text = self._value.__pretty_str__(nesting, indentation)

-        else:

-            text = repr(self._value)

-        return "%s: %s" % (self.__class__.__name__, text)

-    def read(self):

-        self.stream.seek(self.pos)

-        return self.subcon._parse(self.stream, self.context)

-    def dispose(self):

-        self.subcon = None

-        self.stream = None

-        self.context = None

-        self.pos = None

-    def _get_value(self):

-        if self._value is NotImplemented:

-            self._value = self.read()

-        return self._value

-    value = property(_get_value)

-    has_value = property(lambda self: self._value is not NotImplemented)

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

+def recursion_lock(retval, lock_name = "__recursion_lock__"):
+    def decorator(func):
+        def wrapper(self, *args, **kw):
+            if getattr(self, lock_name, False):
+                return retval
+            setattr(self, lock_name, True)
+            try:
+                return func(self, *args, **kw)
+            finally:
+                setattr(self, lock_name, False)
+        wrapper.__name__ = func.__name__
+        return wrapper
+    return decorator
+
+class Container(object):
+    """
+    A generic container of attributes
+    """
+    __slots__ = ["__dict__", "__attrs__"]
+    def __init__(self, **kw):
+        self.__dict__.update(kw)
+        object.__setattr__(self, "__attrs__", kw.keys())
+    
+    def __eq__(self, other):
+        try:
+            return self.__dict__ == other.__dict__
+        except AttributeError:
+            return False
+    def __ne__(self, other):
+        return not (self == other)
+    
+    def __delattr__(self, name):
+        object.__delattr__(self, name)
+        self.__attrs__.remove(name)
+    def __setattr__(self, name, value):
+        d = self.__dict__
+        if name not in d:
+            self.__attrs__.append(name)
+        d[name] = value
+    def __getitem__(self, name):
+        return self.__dict__[name]
+    def __delitem__(self, name):
+        self.__delattr__(name)
+    def __setitem__(self, name, value):
+        self.__setattr__(name, value)
+    def __update__(self, obj):
+        for name in obj.__attrs__:
+            self[name] = obj[name]
+    def __copy__(self):
+        new = self.__class__()
+        new.__attrs__ = self.__attrs__[:]
+        new.__dict__ = self.__dict__.copy()
+        return new
+    
+    @recursion_lock("<...>")
+    def __repr__(self):
+        attrs = sorted("%s = %r" % (k, v) 
+            for k, v in self.__dict__.iteritems() 
+            if not k.startswith("_"))
+        return "%s(%s)" % (self.__class__.__name__, ", ".join(attrs))
+    def __str__(self):
+        return self.__pretty_str__()
+    @recursion_lock("<...>")
+    def __pretty_str__(self, nesting = 1, indentation = "    "):
+        attrs = []
+        ind = indentation * nesting
+        for k in self.__attrs__:
+            v = self.__dict__[k]
+            if not k.startswith("_"):
+                text = [ind, k, " = "]
+                if hasattr(v, "__pretty_str__"):
+                    text.append(v.__pretty_str__(nesting + 1, indentation))
+                else:
+                    text.append(repr(v))
+                attrs.append("".join(text))
+        if not attrs:
+            return "%s()" % (self.__class__.__name__,)
+        attrs.insert(0, self.__class__.__name__ + ":")
+        return "\n".join(attrs)
+
+class FlagsContainer(Container):
+    """
+    A container providing pretty-printing for flags. Only set flags are 
+    displayed. 
+    """
+    def __pretty_str__(self, nesting = 1, indentation = "    "):
+        attrs = []
+        ind = indentation * nesting
+        for k in self.__attrs__:
+            v = self.__dict__[k]
+            if not k.startswith("_") and v:
+                attrs.append(ind + k)
+        if not attrs:
+            return "%s()" % (self.__class__.__name__,)
+        attrs.insert(0, self.__class__.__name__+ ":")
+        return "\n".join(attrs)
+
+class ListContainer(list):
+    """
+    A container for lists
+    """
+    __slots__ = ["__recursion_lock__"]
+    def __str__(self):
+        return self.__pretty_str__()
+    @recursion_lock("[...]")
+    def __pretty_str__(self, nesting = 1, indentation = "    "):
+        if not self:
+            return "[]"
+        ind = indentation * nesting
+        lines = ["["]
+        for elem in self:
+            lines.append("\n")
+            lines.append(ind)
+            if hasattr(elem, "__pretty_str__"):
+                lines.append(elem.__pretty_str__(nesting + 1, indentation))
+            else:
+                lines.append(repr(elem))
+        lines.append("\n")
+        lines.append(indentation * (nesting - 1))
+        lines.append("]")
+        return "".join(lines)
+
+class AttrDict(object):
+    """
+    A dictionary that can be accessed both using indexing and attributes,
+    i.e., 
+        x = AttrDict()
+        x.foo = 5
+        print x["foo"]
+    """
+    __slots__ = ["__dict__"]
+    def __init__(self, **kw):
+        self.__dict__ = kw
+    def __contains__(self, key):
+        return key in self.__dict__
+    def __nonzero__(self):
+        return bool(self.__dict__)
+    def __repr__(self):
+        return repr(self.__dict__)
+    def __str__(self):
+        return self.__pretty_str__()
+    def __pretty_str__(self, nesting = 1, indentation = "    "):
+        if not self:
+            return "{}"
+        text = ["{\n"]
+        ind = nesting * indentation
+        for k in sorted(self.__dict__.keys()):
+            v = self.__dict__[k]
+            text.append(ind)
+            text.append(repr(k))
+            text.append(" : ")
+            if hasattr(v, "__pretty_str__"):
+                try:
+                    text.append(v.__pretty_str__(nesting+1, indentation))
+                except Exception:
+                    text.append(repr(v))
+            else:
+                text.append(repr(v))
+            text.append("\n")
+        text.append((nesting-1) * indentation)
+        text.append("}")
+        return "".join(text)
+    def __delitem__(self, key):
+        del self.__dict__[key]
+    def __getitem__(self, key):
+        return self.__dict__[key]
+    def __setitem__(self, key, value):
+        self.__dict__[key] = value
+    def __copy__(self):
+        new = self.__class__()
+        new.__dict__ = self.__dict__.copy()
+        return new
+    def __update__(self, other):
+        if isinstance(other, dict):
+            self.__dict__.update(other)
+        else:
+            self.__dict__.update(other.__dict__)
+
+class LazyContainer(object):
+    __slots__ = ["subcon", "stream", "pos", "context", "_value"]
+    def __init__(self, subcon, stream, pos, context):
+        self.subcon = subcon
+        self.stream = stream
+        self.pos = pos
+        self.context = context
+        self._value = NotImplemented
+    def __eq__(self, other):
+        try:
+            return self._value == other._value
+        except AttributeError:
+            return False
+    def __ne__(self, other):
+        return not (self == other)
+    def __str__(self):
+        return self.__pretty_str__()
+    def __pretty_str__(self, nesting = 1, indentation = "    "):
+        if self._value is NotImplemented:
+            text = "<unread>"
+        elif hasattr(self._value, "__pretty_str__"):
+            text = self._value.__pretty_str__(nesting, indentation)
+        else:
+            text = repr(self._value)
+        return "%s: %s" % (self.__class__.__name__, text)
+    def read(self):
+        self.stream.seek(self.pos)
+        return self.subcon._parse(self.stream, self.context)
+    def dispose(self):
+        self.subcon = None
+        self.stream = None
+        self.context = None
+        self.pos = None
+    def _get_value(self):
+        if self._value is NotImplemented:
+            self._value = self.read()
+        return self._value
+    value = property(_get_value)
+    has_value = property(lambda self: self._value is not NotImplemented)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/elftools/construct/lib/hex.py b/elftools/construct/lib/hex.py
index e392bd3..0bb2f02 100644
--- a/elftools/construct/lib/hex.py
+++ b/elftools/construct/lib/hex.py
@@ -1,34 +1,34 @@
-_printable = dict((chr(i), ".") for i in range(256))

-_printable.update((chr(i), chr(i)) for i in range(32, 128))

-

-def hexdump(data, linesize = 16):

-    prettylines = []

-    if len(data) < 65536:

-        fmt = "%%04X   %%-%ds   %%s"

-    else:

-        fmt = "%%08X   %%-%ds   %%s"

-    fmt = fmt % (3 * linesize - 1,)

-    for i in xrange(0, len(data), linesize):

-        line = data[i : i + linesize]

-        hextext = " ".join(b.encode("hex") for b in line)

-        rawtext = "".join(_printable[b] for b in line)

-        prettylines.append(fmt % (i, hextext, rawtext))

-    return prettylines

-

-class HexString(str):

-    """

-    represents a string that will be hex-dumped (only via __pretty_str__).

-    this class derives of str, and behaves just like a normal string in all

-    other contexts.

-    """

-    def __init__(self, data, linesize = 16):

-        str.__init__(self, data)

-        self.linesize = linesize

-    def __new__(cls, data, *args, **kwargs):

-        return str.__new__(cls, data)

-    def __pretty_str__(self, nesting = 1, indentation = "    "):

-        sep = "\n" + indentation * nesting

-        return sep + sep.join(hexdump(self))

-

-

-

+_printable = dict((chr(i), ".") for i in range(256))
+_printable.update((chr(i), chr(i)) for i in range(32, 128))
+
+def hexdump(data, linesize = 16):
+    prettylines = []
+    if len(data) < 65536:
+        fmt = "%%04X   %%-%ds   %%s"
+    else:
+        fmt = "%%08X   %%-%ds   %%s"
+    fmt = fmt % (3 * linesize - 1,)
+    for i in xrange(0, len(data), linesize):
+        line = data[i : i + linesize]
+        hextext = " ".join(b.encode("hex") for b in line)
+        rawtext = "".join(_printable[b] for b in line)
+        prettylines.append(fmt % (i, hextext, rawtext))
+    return prettylines
+
+class HexString(str):
+    """
+    represents a string that will be hex-dumped (only via __pretty_str__).
+    this class derives of str, and behaves just like a normal string in all
+    other contexts.
+    """
+    def __init__(self, data, linesize = 16):
+        str.__init__(self, data)
+        self.linesize = linesize
+    def __new__(cls, data, *args, **kwargs):
+        return str.__new__(cls, data)
+    def __pretty_str__(self, nesting = 1, indentation = "    "):
+        sep = "\n" + indentation * nesting
+        return sep + sep.join(hexdump(self))
+
+
+
diff --git a/elftools/construct/lib/utils.py b/elftools/construct/lib/utils.py
index 968dc26..86d8b03 100644
--- a/elftools/construct/lib/utils.py
+++ b/elftools/construct/lib/utils.py
@@ -1,22 +1,22 @@
-try:

-    from cStringIO import StringIO

-except ImportError:

-    from StringIO import StringIO

-

-

-try:

-    from struct import Struct as Packer

-except ImportError:

-    from struct import pack, unpack, calcsize

-    class Packer(object):

-        __slots__ = ["format", "size"]

-        def __init__(self, format):

-            self.format = format

-            self.size = calcsize(format)

-        def pack(self, *args):

-            return pack(self.format, *args)

-        def unpack(self, data):

-            return unpack(self.format, data)

-

-

-

+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+
+try:
+    from struct import Struct as Packer
+except ImportError:
+    from struct import pack, unpack, calcsize
+    class Packer(object):
+        __slots__ = ["format", "size"]
+        def __init__(self, format):
+            self.format = format
+            self.size = calcsize(format)
+        def pack(self, *args):
+            return pack(self.format, *args)
+        def unpack(self, data):
+            return unpack(self.format, data)
+
+
+
diff --git a/elftools/construct/macros.py b/elftools/construct/macros.py
index 35e689a..dcffb0e 100644
--- a/elftools/construct/macros.py
+++ b/elftools/construct/macros.py
@@ -1,514 +1,514 @@
-from lib import BitStreamReader, BitStreamWriter, encode_bin, decode_bin

-from core import *

-from adapters import *

-

-

-#===============================================================================

-# fields

-#===============================================================================

-def Field(name, length):

-    """a field

-    * name - the name of the field

-    * length - the length of the field. the length can be either an integer

-      (StaticField), or a function that takes the context as an argument and 

-      returns the length (MetaField)

-    """

-    if callable(length):

-        return MetaField(name, length)

-    else:

-        return StaticField(name, length)

-

-def BitField(name, length, swapped = False, signed = False, bytesize = 8):

-    """a bit field; must be enclosed in a BitStruct

-    * name - the name of the field

-    * length - the length of the field in bits. the length can be either 

-      an integer, or a function that takes the context as an argument and 

-      returns the length

-    * swapped - whether the value is byte-swapped (little endian). the 

-      default is False.

-    * signed - whether the value of the bitfield is a signed integer. the 

-      default is False.

-    * bytesize - the number of bits in a byte (used for byte-swapping). the

-      default is 8.

-    """

-    return BitIntegerAdapter(Field(name, length), 

-        length,

-        swapped = swapped, 

-        signed = signed,

-        bytesize = bytesize

-    )

-

-def Padding(length, pattern = "\x00", strict = False):

-    r"""a padding field (value is discarded)

-    * length - the length of the field. the length can be either an integer,

-      or a function that takes the context as an argument and returns the 

-      length

-    * pattern - the padding pattern (character) to use. default is "\x00"

-    * strict - whether or not to raise an exception is the actual padding 

-      pattern mismatches the desired pattern. default is False.

-    """

-    return PaddingAdapter(Field(None, length), 

-        pattern = pattern, 

-        strict = strict,

-    )

-

-def Flag(name, truth = 1, falsehood = 0, default = False):

-    """a flag field (True or False)

-    * name - the name of the field

-    * truth - the numeric value of truth. the default is 1.

-    * falsehood - the numeric value of falsehood. the default is 0.

-    * default - the default value to assume, when the value is neither 

-      `truth` nor `falsehood`. the default is False.

-    """

-    return SymmetricMapping(Field(name, 1), 

-        {True : chr(truth), False : chr(falsehood)},

-        default = default,

-    )

-

-#===============================================================================

-# field shortcuts

-#===============================================================================

-def Bit(name):

-    """a 1-bit BitField; must be enclosed in a BitStruct"""

-    return BitField(name, 1)

-def Nibble(name):

-    """a 4-bit BitField; must be enclosed in a BitStruct"""

-    return BitField(name, 4)

-def Octet(name):

-    """an 8-bit BitField; must be enclosed in a BitStruct"""

-    return BitField(name, 8)

-

-def UBInt8(name):

-    """unsigned, big endian 8-bit integer"""

-    return FormatField(name, ">", "B")

-def UBInt16(name):

-    """unsigned, big endian 16-bit integer"""

-    return FormatField(name, ">", "H")

-def UBInt32(name):

-    """unsigned, big endian 32-bit integer"""

-    return FormatField(name, ">", "L")

-def UBInt64(name):

-    """unsigned, big endian 64-bit integer"""

-    return FormatField(name, ">", "Q")

-

-def SBInt8(name):

-    """signed, big endian 8-bit integer"""

-    return FormatField(name, ">", "b")

-def SBInt16(name):

-    """signed, big endian 16-bit integer"""

-    return FormatField(name, ">", "h")

-def SBInt32(name):

-    """signed, big endian 32-bit integer"""

-    return FormatField(name, ">", "l")

-def SBInt64(name):

-    """signed, big endian 64-bit integer"""

-    return FormatField(name, ">", "q")

-

-def ULInt8(name):

-    """unsigned, little endian 8-bit integer"""

-    return FormatField(name, "<", "B")

-def ULInt16(name):

-    """unsigned, little endian 16-bit integer"""

-    return FormatField(name, "<", "H")

-def ULInt32(name):

-    """unsigned, little endian 32-bit integer"""

-    return FormatField(name, "<", "L")

-def ULInt64(name):

-    """unsigned, little endian 64-bit integer"""

-    return FormatField(name, "<", "Q")

-

-def SLInt8(name):

-    """signed, little endian 8-bit integer"""

-    return FormatField(name, "<", "b")

-def SLInt16(name):

-    """signed, little endian 16-bit integer"""

-    return FormatField(name, "<", "h")

-def SLInt32(name):

-    """signed, little endian 32-bit integer"""

-    return FormatField(name, "<", "l")

-def SLInt64(name):

-    """signed, little endian 64-bit integer"""

-    return FormatField(name, "<", "q")

-

-def UNInt8(name):

-    """unsigned, native endianity 8-bit integer"""

-    return FormatField(name, "=", "B")

-def UNInt16(name):

-    """unsigned, native endianity 16-bit integer"""

-    return FormatField(name, "=", "H")

-def UNInt32(name):

-    """unsigned, native endianity 32-bit integer"""

-    return FormatField(name, "=", "L")

-def UNInt64(name):

-    """unsigned, native endianity 64-bit integer"""

-    return FormatField(name, "=", "Q")

-

-def SNInt8(name):

-    """signed, native endianity 8-bit integer"""

-    return FormatField(name, "=", "b")

-def SNInt16(name):

-    """signed, native endianity 16-bit integer"""

-    return FormatField(name, "=", "h")

-def SNInt32(name):

-    """signed, native endianity 32-bit integer"""

-    return FormatField(name, "=", "l")

-def SNInt64(name):

-    """signed, native endianity 64-bit integer"""

-    return FormatField(name, "=", "q")

-

-def BFloat32(name):

-    """big endian, 32-bit IEEE floating point number"""

-    return FormatField(name, ">", "f")

-def LFloat32(name):

-    """little endian, 32-bit IEEE floating point number"""

-    return FormatField(name, "<", "f")

-def NFloat32(name):

-    """native endianity, 32-bit IEEE floating point number"""

-    return FormatField(name, "=", "f")

-

-def BFloat64(name):

-    """big endian, 64-bit IEEE floating point number"""

-    return FormatField(name, ">", "d")

-def LFloat64(name):

-    """little endian, 64-bit IEEE floating point number"""

-    return FormatField(name, "<", "d")

-def NFloat64(name):

-    """native endianity, 64-bit IEEE floating point number"""

-    return FormatField(name, "=", "d")

-

-

-#===============================================================================

-# arrays

-#===============================================================================

-def Array(count, subcon):

-    """array of subcon repeated count times.

-    * subcon - the subcon.

-    * count - an integer, or a function taking the context as an argument, 

-      returning the count

-    """

-    if callable(count):

-        con = MetaArray(count, subcon)

-    else:

-        con = MetaArray(lambda ctx: count, subcon)

-        con._clear_flag(con.FLAG_DYNAMIC)

-    return con

-

-def PrefixedArray(subcon, length_field = UBInt8("length")):

-    """an array prefixed by a length field.

-    * subcon - the subcon to be repeated

-    * length_field - an integer construct

-    """

-    return LengthValueAdapter(

-        Sequence(subcon.name, 

-            length_field, 

-            Array(lambda ctx: ctx[length_field.name], subcon),

-            nested = False

-        )

-    )

-

-def OpenRange(mincount, subcon):

-    from sys import maxint

-    return Range(mincount, maxint, subcon)

-

-def GreedyRange(subcon):

-    """an open range (1 or more times) of repeated subcon.

-    * subcon - the subcon to repeat"""

-    return OpenRange(1, subcon)

-

-def OptionalGreedyRange(subcon):

-    """an open range (0 or more times) of repeated subcon.

-    * subcon - the subcon to repeat"""

-    return OpenRange(0, subcon)

-

-

-#===============================================================================

-# subconstructs

-#===============================================================================

-def Optional(subcon):

-    """an optional construct. if parsing fails, returns None.

-    * subcon - the subcon to optionally parse or build

-    """

-    return Select(subcon.name, subcon, Pass)

-

-def Bitwise(subcon):

-    """converts the stream to bits, and passes the bitstream to subcon

-    * subcon - a bitwise construct (usually BitField)

-    """

-    # subcons larger than MAX_BUFFER will be wrapped by Restream instead 

-    # of Buffered. implementation details, don't stick your nose :)

-    MAX_BUFFER = 1024 * 8

-    def resizer(length):

-        if length & 7:

-            raise SizeofError("size must be a multiple of 8", length)

-        return length >> 3

-    if not subcon._is_flag(subcon.FLAG_DYNAMIC) and subcon.sizeof() < MAX_BUFFER:

-        con = Buffered(subcon, 

-            encoder = decode_bin, 

-            decoder = encode_bin, 

-            resizer = resizer

-        )

-    else:

-        con = Restream(subcon, 

-            stream_reader = BitStreamReader, 

-            stream_writer = BitStreamWriter, 

-            resizer = resizer)

-    return con

-

-def Aligned(subcon, modulus = 4, pattern = "\x00"):

-    r"""aligns subcon to modulus boundary using padding pattern

-    * subcon - the subcon to align

-    * modulus - the modulus boundary (default is 4)

-    * pattern - the padding pattern (default is \x00)

-    """

-    if modulus < 2:

-        raise ValueError("modulus must be >= 2", modulus)

-    if modulus in (2, 4, 8, 16, 32, 64, 128, 256, 512, 1024):

-        def padlength(ctx):

-            m1 = modulus - 1

-            return (modulus - (subcon._sizeof(ctx) & m1)) & m1

-    else:

-        def padlength(ctx):

-            return (modulus - (subcon._sizeof(ctx) % modulus)) % modulus

-    return IndexingAdapter(

-        Sequence(subcon.name, 

-            subcon, 

-            Padding(padlength, pattern = pattern),

-            nested = False,

-        ),

-        0

-    )

-

-def Embedded(subcon):

-    """embeds a struct into the enclosing struct.

-    * subcon - the struct to embed

-    """

-    return Reconfig(subcon.name, subcon, subcon.FLAG_EMBED)

-

-def Rename(newname, subcon):

-    """renames an existing construct

-    * newname - the new name

-    * subcon - the subcon to rename

-    """

-    return Reconfig(newname, subcon)

-

-def Alias(newname, oldname):

-    """creates an alias for an existing element in a struct

-    * newname - the new name

-    * oldname - the name of an existing element

-    """

-    return Value(newname, lambda ctx: ctx[oldname])

-

-

-#===============================================================================

-# mapping

-#===============================================================================

-def SymmetricMapping(subcon, mapping, default = NotImplemented):

-    """defines a symmetrical mapping: a->b, b->a.

-    * subcon - the subcon to map

-    * mapping - the encoding mapping (a dict); the decoding mapping is 

-      achieved by reversing this mapping

-    * default - the default value to use when no mapping is found. if no 

-      default value is given, and exception is raised. setting to Pass would

-      return the value "as is" (unmapped)

-    """

-    reversed_mapping = dict((v, k) for k, v in mapping.iteritems())

-    return MappingAdapter(subcon, 

-        encoding = mapping, 

-        decoding = reversed_mapping, 

-        encdefault = default,

-        decdefault = default, 

-    )

-

-def Enum(subcon, **kw):

-    """a set of named values mapping. 

-    * subcon - the subcon to map

-    * kw - keyword arguments which serve as the encoding mapping

-    * _default_ - an optional, keyword-only argument that specifies the 

-      default value to use when the mapping is undefined. if not given,

-      and exception is raised when the mapping is undefined. use `Pass` to

-      pass the unmapped value as-is

-    """

-    return SymmetricMapping(subcon, kw, kw.pop("_default_", NotImplemented))

-

-def FlagsEnum(subcon, **kw):

-    """a set of flag values mapping.

-    * subcon - the subcon to map

-    * kw - keyword arguments which serve as the encoding mapping

-    """

-    return FlagsAdapter(subcon, kw)

-

-

-#===============================================================================

-# structs

-#===============================================================================

-def AlignedStruct(name, *subcons, **kw):

-    """a struct of aligned fields

-    * name - the name of the struct

-    * subcons - the subcons that make up this structure

-    * kw - keyword arguments to pass to Aligned: 'modulus' and 'pattern'

-    """

-    return Struct(name, *(Aligned(sc, **kw) for sc in subcons))

-

-def BitStruct(name, *subcons):

-    """a struct of bitwise fields

-    * name - the name of the struct

-    * subcons - the subcons that make up this structure

-    """

-    return Bitwise(Struct(name, *subcons))

-

-def EmbeddedBitStruct(*subcons):

-    """an embedded BitStruct. no name is necessary.

-    * subcons - the subcons that make up this structure

-    """

-    return Bitwise(Embedded(Struct(None, *subcons)))

-

-#===============================================================================

-# strings

-#===============================================================================

-def String(name, length, encoding = None, padchar = None, 

-           paddir = "right", trimdir = "right"):

-    """a fixed-length, optionally padded string of characters

-    * name - the name of the field

-    * length - the length (integer)

-    * encoding - the encoding to use (e.g., "utf8"), or None, for raw bytes.

-      default is None

-    * padchar - the padding character (commonly "\x00"), or None to 

-      disable padding. default is None

-    * paddir - the direction where padding is placed ("right", "left", or 

-      "center"). the default is "right". this argument is meaningless if 

-      padchar is None.

-    * trimdir - the direction where trimming will take place ("right" or 

-      "left"). the default is "right". trimming is only meaningful for

-      building, when the given string is too long. this argument is 

-      meaningless if padchar is None.

-    """

-    con = StringAdapter(Field(name, length), encoding = encoding)

-    if padchar is not None:

-        con = PaddedStringAdapter(con, 

-            padchar = padchar, 

-            paddir = paddir, 

-            trimdir = trimdir

-        )

-    return con

-

-def PascalString(name, length_field = UBInt8("length"), encoding = None):

-    """a string prefixed with a length field. the data must directly follow 

-    the length field.

-    * name - the name of the 

-    * length_field - a numeric construct (i.e., UBInt8) that holds the 

-      length. default is an unsigned, 8-bit integer field. note that this

-      argument must pass an instance of a construct, not a class 

-      (`UBInt8("length")` rather than `UBInt8`)

-    * encoding - the encoding to use (e.g., "utf8"), or None, for raw bytes.

-      default is None

-    """

-    return StringAdapter(

-        LengthValueAdapter(

-            Sequence(name,

-                length_field,

-                Field("data", lambda ctx: ctx[length_field.name]),

-            )

-        ),

-        encoding = encoding,

-    )

-

-def CString(name, terminators = "\x00", encoding = None, 

-            char_field = Field(None, 1)):

-    r"""a c-style string (string terminated by a terminator char)

-    * name - the name fo the string

-    * terminators - a sequence of terminator chars. default is "\x00".

-    * encoding - the encoding to use (e.g., "utf8"), or None, for raw bytes.

-      default is None

-    * char_field - the construct that represents a single character. default

-      is a one-byte character. note that this argument must be an instance

-      of a construct, not a construct class (`Field("char", 1)` rather than

-      `Field`)

-    """

-    return Rename(name,

-        CStringAdapter(

-            RepeatUntil(lambda obj, ctx: obj in terminators, 

-                char_field,

-            ),

-            terminators = terminators,

-            encoding = encoding,

-        )

-    )

-

-

-#===============================================================================

-# conditional

-#===============================================================================

-def IfThenElse(name, predicate, then_subcon, else_subcon):

-    """an if-then-else conditional construct: if the predicate indicates True,

-    `then_subcon` will be used; otherwise `else_subcon`

-    * name - the name of the construct

-    * predicate - a function taking the context as an argument and returning

-      True or False

-    * then_subcon - the subcon that will be used if the predicate returns True

-    * else_subcon - the subcon that will be used if the predicate returns False

-    """

-    return Switch(name, lambda ctx: bool(predicate(ctx)),

-        {

-            True : then_subcon,

-            False : else_subcon,

-        }

-    )

-

-def If(predicate, subcon, elsevalue = None):

-    """an if-then conditional construct: if the predicate indicates True,

-    subcon will be used; otherwise, `elsevalue` will be returned instead.

-    * predicate - a function taking the context as an argument and returning

-      True or False

-    * subcon - the subcon that will be used if the predicate returns True

-    * elsevalue - the value that will be used should the predicate return False.

-      by default this value is None.

-    """

-    return IfThenElse(subcon.name, 

-        predicate, 

-        subcon, 

-        Value("elsevalue", lambda ctx: elsevalue)

-    )

-

-

-#===============================================================================

-# misc

-#===============================================================================

-def OnDemandPointer(offsetfunc, subcon, force_build = True):

-    """an on-demand pointer. 

-    * offsetfunc - a function taking the context as an argument and returning 

-      the absolute stream position

-    * subcon - the subcon that will be parsed from the `offsetfunc()` stream 

-      position on demand

-    * force_build - see OnDemand. by default True.

-    """

-    return OnDemand(Pointer(offsetfunc, subcon), 

-        advance_stream = False, 

-        force_build = force_build

-    )

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

+from lib import BitStreamReader, BitStreamWriter, encode_bin, decode_bin
+from core import *
+from adapters import *
+
+
+#===============================================================================
+# fields
+#===============================================================================
+def Field(name, length):
+    """a field
+    * name - the name of the field
+    * length - the length of the field. the length can be either an integer
+      (StaticField), or a function that takes the context as an argument and 
+      returns the length (MetaField)
+    """
+    if callable(length):
+        return MetaField(name, length)
+    else:
+        return StaticField(name, length)
+
+def BitField(name, length, swapped = False, signed = False, bytesize = 8):
+    """a bit field; must be enclosed in a BitStruct
+    * name - the name of the field
+    * length - the length of the field in bits. the length can be either 
+      an integer, or a function that takes the context as an argument and 
+      returns the length
+    * swapped - whether the value is byte-swapped (little endian). the 
+      default is False.
+    * signed - whether the value of the bitfield is a signed integer. the 
+      default is False.
+    * bytesize - the number of bits in a byte (used for byte-swapping). the
+      default is 8.
+    """
+    return BitIntegerAdapter(Field(name, length), 
+        length,
+        swapped = swapped, 
+        signed = signed,
+        bytesize = bytesize
+    )
+
+def Padding(length, pattern = "\x00", strict = False):
+    r"""a padding field (value is discarded)
+    * length - the length of the field. the length can be either an integer,
+      or a function that takes the context as an argument and returns the 
+      length
+    * pattern - the padding pattern (character) to use. default is "\x00"
+    * strict - whether or not to raise an exception is the actual padding 
+      pattern mismatches the desired pattern. default is False.
+    """
+    return PaddingAdapter(Field(None, length), 
+        pattern = pattern, 
+        strict = strict,
+    )
+
+def Flag(name, truth = 1, falsehood = 0, default = False):
+    """a flag field (True or False)
+    * name - the name of the field
+    * truth - the numeric value of truth. the default is 1.
+    * falsehood - the numeric value of falsehood. the default is 0.
+    * default - the default value to assume, when the value is neither 
+      `truth` nor `falsehood`. the default is False.
+    """
+    return SymmetricMapping(Field(name, 1), 
+        {True : chr(truth), False : chr(falsehood)},
+        default = default,
+    )
+
+#===============================================================================
+# field shortcuts
+#===============================================================================
+def Bit(name):
+    """a 1-bit BitField; must be enclosed in a BitStruct"""
+    return BitField(name, 1)
+def Nibble(name):
+    """a 4-bit BitField; must be enclosed in a BitStruct"""
+    return BitField(name, 4)
+def Octet(name):
+    """an 8-bit BitField; must be enclosed in a BitStruct"""
+    return BitField(name, 8)
+
+def UBInt8(name):
+    """unsigned, big endian 8-bit integer"""
+    return FormatField(name, ">", "B")
+def UBInt16(name):
+    """unsigned, big endian 16-bit integer"""
+    return FormatField(name, ">", "H")
+def UBInt32(name):
+    """unsigned, big endian 32-bit integer"""
+    return FormatField(name, ">", "L")
+def UBInt64(name):
+    """unsigned, big endian 64-bit integer"""
+    return FormatField(name, ">", "Q")
+
+def SBInt8(name):
+    """signed, big endian 8-bit integer"""
+    return FormatField(name, ">", "b")
+def SBInt16(name):
+    """signed, big endian 16-bit integer"""
+    return FormatField(name, ">", "h")
+def SBInt32(name):
+    """signed, big endian 32-bit integer"""
+    return FormatField(name, ">", "l")
+def SBInt64(name):
+    """signed, big endian 64-bit integer"""
+    return FormatField(name, ">", "q")
+
+def ULInt8(name):
+    """unsigned, little endian 8-bit integer"""
+    return FormatField(name, "<", "B")
+def ULInt16(name):
+    """unsigned, little endian 16-bit integer"""
+    return FormatField(name, "<", "H")
+def ULInt32(name):
+    """unsigned, little endian 32-bit integer"""
+    return FormatField(name, "<", "L")
+def ULInt64(name):
+    """unsigned, little endian 64-bit integer"""
+    return FormatField(name, "<", "Q")
+
+def SLInt8(name):
+    """signed, little endian 8-bit integer"""
+    return FormatField(name, "<", "b")
+def SLInt16(name):
+    """signed, little endian 16-bit integer"""
+    return FormatField(name, "<", "h")
+def SLInt32(name):
+    """signed, little endian 32-bit integer"""
+    return FormatField(name, "<", "l")
+def SLInt64(name):
+    """signed, little endian 64-bit integer"""
+    return FormatField(name, "<", "q")
+
+def UNInt8(name):
+    """unsigned, native endianity 8-bit integer"""
+    return FormatField(name, "=", "B")
+def UNInt16(name):
+    """unsigned, native endianity 16-bit integer"""
+    return FormatField(name, "=", "H")
+def UNInt32(name):
+    """unsigned, native endianity 32-bit integer"""
+    return FormatField(name, "=", "L")
+def UNInt64(name):
+    """unsigned, native endianity 64-bit integer"""
+    return FormatField(name, "=", "Q")
+
+def SNInt8(name):
+    """signed, native endianity 8-bit integer"""
+    return FormatField(name, "=", "b")
+def SNInt16(name):
+    """signed, native endianity 16-bit integer"""
+    return FormatField(name, "=", "h")
+def SNInt32(name):
+    """signed, native endianity 32-bit integer"""
+    return FormatField(name, "=", "l")
+def SNInt64(name):
+    """signed, native endianity 64-bit integer"""
+    return FormatField(name, "=", "q")
+
+def BFloat32(name):
+    """big endian, 32-bit IEEE floating point number"""
+    return FormatField(name, ">", "f")
+def LFloat32(name):
+    """little endian, 32-bit IEEE floating point number"""
+    return FormatField(name, "<", "f")
+def NFloat32(name):
+    """native endianity, 32-bit IEEE floating point number"""
+    return FormatField(name, "=", "f")
+
+def BFloat64(name):
+    """big endian, 64-bit IEEE floating point number"""
+    return FormatField(name, ">", "d")
+def LFloat64(name):
+    """little endian, 64-bit IEEE floating point number"""
+    return FormatField(name, "<", "d")
+def NFloat64(name):
+    """native endianity, 64-bit IEEE floating point number"""
+    return FormatField(name, "=", "d")
+
+
+#===============================================================================
+# arrays
+#===============================================================================
+def Array(count, subcon):
+    """array of subcon repeated count times.
+    * subcon - the subcon.
+    * count - an integer, or a function taking the context as an argument, 
+      returning the count
+    """
+    if callable(count):
+        con = MetaArray(count, subcon)
+    else:
+        con = MetaArray(lambda ctx: count, subcon)
+        con._clear_flag(con.FLAG_DYNAMIC)
+    return con
+
+def PrefixedArray(subcon, length_field = UBInt8("length")):
+    """an array prefixed by a length field.
+    * subcon - the subcon to be repeated
+    * length_field - an integer construct
+    """
+    return LengthValueAdapter(
+        Sequence(subcon.name, 
+            length_field, 
+            Array(lambda ctx: ctx[length_field.name], subcon),
+            nested = False
+        )
+    )
+
+def OpenRange(mincount, subcon):
+    from sys import maxint
+    return Range(mincount, maxint, subcon)
+
+def GreedyRange(subcon):
+    """an open range (1 or more times) of repeated subcon.
+    * subcon - the subcon to repeat"""
+    return OpenRange(1, subcon)
+
+def OptionalGreedyRange(subcon):
+    """an open range (0 or more times) of repeated subcon.
+    * subcon - the subcon to repeat"""
+    return OpenRange(0, subcon)
+
+
+#===============================================================================
+# subconstructs
+#===============================================================================
+def Optional(subcon):
+    """an optional construct. if parsing fails, returns None.
+    * subcon - the subcon to optionally parse or build
+    """
+    return Select(subcon.name, subcon, Pass)
+
+def Bitwise(subcon):
+    """converts the stream to bits, and passes the bitstream to subcon
+    * subcon - a bitwise construct (usually BitField)
+    """
+    # subcons larger than MAX_BUFFER will be wrapped by Restream instead 
+    # of Buffered. implementation details, don't stick your nose :)
+    MAX_BUFFER = 1024 * 8
+    def resizer(length):
+        if length & 7:
+            raise SizeofError("size must be a multiple of 8", length)
+        return length >> 3
+    if not subcon._is_flag(subcon.FLAG_DYNAMIC) and subcon.sizeof() < MAX_BUFFER:
+        con = Buffered(subcon, 
+            encoder = decode_bin, 
+            decoder = encode_bin, 
+            resizer = resizer
+        )
+    else:
+        con = Restream(subcon, 
+            stream_reader = BitStreamReader, 
+            stream_writer = BitStreamWriter, 
+            resizer = resizer)
+    return con
+
+def Aligned(subcon, modulus = 4, pattern = "\x00"):
+    r"""aligns subcon to modulus boundary using padding pattern
+    * subcon - the subcon to align
+    * modulus - the modulus boundary (default is 4)
+    * pattern - the padding pattern (default is \x00)
+    """
+    if modulus < 2:
+        raise ValueError("modulus must be >= 2", modulus)
+    if modulus in (2, 4, 8, 16, 32, 64, 128, 256, 512, 1024):
+        def padlength(ctx):
+            m1 = modulus - 1
+            return (modulus - (subcon._sizeof(ctx) & m1)) & m1
+    else:
+        def padlength(ctx):
+            return (modulus - (subcon._sizeof(ctx) % modulus)) % modulus
+    return IndexingAdapter(
+        Sequence(subcon.name, 
+            subcon, 
+            Padding(padlength, pattern = pattern),
+            nested = False,
+        ),
+        0
+    )
+
+def Embedded(subcon):
+    """embeds a struct into the enclosing struct.
+    * subcon - the struct to embed
+    """
+    return Reconfig(subcon.name, subcon, subcon.FLAG_EMBED)
+
+def Rename(newname, subcon):
+    """renames an existing construct
+    * newname - the new name
+    * subcon - the subcon to rename
+    """
+    return Reconfig(newname, subcon)
+
+def Alias(newname, oldname):
+    """creates an alias for an existing element in a struct
+    * newname - the new name
+    * oldname - the name of an existing element
+    """
+    return Value(newname, lambda ctx: ctx[oldname])
+
+
+#===============================================================================
+# mapping
+#===============================================================================
+def SymmetricMapping(subcon, mapping, default = NotImplemented):
+    """defines a symmetrical mapping: a->b, b->a.
+    * subcon - the subcon to map
+    * mapping - the encoding mapping (a dict); the decoding mapping is 
+      achieved by reversing this mapping
+    * default - the default value to use when no mapping is found. if no 
+      default value is given, and exception is raised. setting to Pass would
+      return the value "as is" (unmapped)
+    """
+    reversed_mapping = dict((v, k) for k, v in mapping.iteritems())
+    return MappingAdapter(subcon, 
+        encoding = mapping, 
+        decoding = reversed_mapping, 
+        encdefault = default,
+        decdefault = default, 
+    )
+
+def Enum(subcon, **kw):
+    """a set of named values mapping. 
+    * subcon - the subcon to map
+    * kw - keyword arguments which serve as the encoding mapping
+    * _default_ - an optional, keyword-only argument that specifies the 
+      default value to use when the mapping is undefined. if not given,
+      and exception is raised when the mapping is undefined. use `Pass` to
+      pass the unmapped value as-is
+    """
+    return SymmetricMapping(subcon, kw, kw.pop("_default_", NotImplemented))
+
+def FlagsEnum(subcon, **kw):
+    """a set of flag values mapping.
+    * subcon - the subcon to map
+    * kw - keyword arguments which serve as the encoding mapping
+    """
+    return FlagsAdapter(subcon, kw)
+
+
+#===============================================================================
+# structs
+#===============================================================================
+def AlignedStruct(name, *subcons, **kw):
+    """a struct of aligned fields
+    * name - the name of the struct
+    * subcons - the subcons that make up this structure
+    * kw - keyword arguments to pass to Aligned: 'modulus' and 'pattern'
+    """
+    return Struct(name, *(Aligned(sc, **kw) for sc in subcons))
+
+def BitStruct(name, *subcons):
+    """a struct of bitwise fields
+    * name - the name of the struct
+    * subcons - the subcons that make up this structure
+    """
+    return Bitwise(Struct(name, *subcons))
+
+def EmbeddedBitStruct(*subcons):
+    """an embedded BitStruct. no name is necessary.
+    * subcons - the subcons that make up this structure
+    """
+    return Bitwise(Embedded(Struct(None, *subcons)))
+
+#===============================================================================
+# strings
+#===============================================================================
+def String(name, length, encoding = None, padchar = None, 
+           paddir = "right", trimdir = "right"):
+    """a fixed-length, optionally padded string of characters
+    * name - the name of the field
+    * length - the length (integer)
+    * encoding - the encoding to use (e.g., "utf8"), or None, for raw bytes.
+      default is None
+    * padchar - the padding character (commonly "\x00"), or None to 
+      disable padding. default is None
+    * paddir - the direction where padding is placed ("right", "left", or 
+      "center"). the default is "right". this argument is meaningless if 
+      padchar is None.
+    * trimdir - the direction where trimming will take place ("right" or 
+      "left"). the default is "right". trimming is only meaningful for
+      building, when the given string is too long. this argument is 
+      meaningless if padchar is None.
+    """
+    con = StringAdapter(Field(name, length), encoding = encoding)
+    if padchar is not None:
+        con = PaddedStringAdapter(con, 
+            padchar = padchar, 
+            paddir = paddir, 
+            trimdir = trimdir
+        )
+    return con
+
+def PascalString(name, length_field = UBInt8("length"), encoding = None):
+    """a string prefixed with a length field. the data must directly follow 
+    the length field.
+    * name - the name of the 
+    * length_field - a numeric construct (i.e., UBInt8) that holds the 
+      length. default is an unsigned, 8-bit integer field. note that this
+      argument must pass an instance of a construct, not a class 
+      (`UBInt8("length")` rather than `UBInt8`)
+    * encoding - the encoding to use (e.g., "utf8"), or None, for raw bytes.
+      default is None
+    """
+    return StringAdapter(
+        LengthValueAdapter(
+            Sequence(name,
+                length_field,
+                Field("data", lambda ctx: ctx[length_field.name]),
+            )
+        ),
+        encoding = encoding,
+    )
+
+def CString(name, terminators = "\x00", encoding = None, 
+            char_field = Field(None, 1)):
+    r"""a c-style string (string terminated by a terminator char)
+    * name - the name fo the string
+    * terminators - a sequence of terminator chars. default is "\x00".
+    * encoding - the encoding to use (e.g., "utf8"), or None, for raw bytes.
+      default is None
+    * char_field - the construct that represents a single character. default
+      is a one-byte character. note that this argument must be an instance
+      of a construct, not a construct class (`Field("char", 1)` rather than
+      `Field`)
+    """
+    return Rename(name,
+        CStringAdapter(
+            RepeatUntil(lambda obj, ctx: obj in terminators, 
+                char_field,
+            ),
+            terminators = terminators,
+            encoding = encoding,
+        )
+    )
+
+
+#===============================================================================
+# conditional
+#===============================================================================
+def IfThenElse(name, predicate, then_subcon, else_subcon):
+    """an if-then-else conditional construct: if the predicate indicates True,
+    `then_subcon` will be used; otherwise `else_subcon`
+    * name - the name of the construct
+    * predicate - a function taking the context as an argument and returning
+      True or False
+    * then_subcon - the subcon that will be used if the predicate returns True
+    * else_subcon - the subcon that will be used if the predicate returns False
+    """
+    return Switch(name, lambda ctx: bool(predicate(ctx)),
+        {
+            True : then_subcon,
+            False : else_subcon,
+        }
+    )
+
+def If(predicate, subcon, elsevalue = None):
+    """an if-then conditional construct: if the predicate indicates True,
+    subcon will be used; otherwise, `elsevalue` will be returned instead.
+    * predicate - a function taking the context as an argument and returning
+      True or False
+    * subcon - the subcon that will be used if the predicate returns True
+    * elsevalue - the value that will be used should the predicate return False.
+      by default this value is None.
+    """
+    return IfThenElse(subcon.name, 
+        predicate, 
+        subcon, 
+        Value("elsevalue", lambda ctx: elsevalue)
+    )
+
+
+#===============================================================================
+# misc
+#===============================================================================
+def OnDemandPointer(offsetfunc, subcon, force_build = True):
+    """an on-demand pointer. 
+    * offsetfunc - a function taking the context as an argument and returning 
+      the absolute stream position
+    * subcon - the subcon that will be parsed from the `offsetfunc()` stream 
+      position on demand
+    * force_build - see OnDemand. by default True.
+    """
+    return OnDemand(Pointer(offsetfunc, subcon), 
+        advance_stream = False, 
+        force_build = force_build
+    )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/elftools/construct/text.py b/elftools/construct/text.py
index dee47a1..e461dff 100644
--- a/elftools/construct/text.py
+++ b/elftools/construct/text.py
@@ -1,286 +1,286 @@
-from core import *

-from adapters import *

-from macros import *

-

-

-#===============================================================================

-# exceptions

-#===============================================================================

-class QuotedStringError(ConstructError):

-    __slots__ = []

-

-

-#===============================================================================

-# constructs

-#===============================================================================

-class QuotedString(Construct):

-    r"""

-    A quoted string (begins with an opening-quote, terminated by a 

-    closing-quote, which may be escaped by an escape character)

-    

-    Parameters:

-    * name - the name of the field

-    * start_quote - the opening quote character. default is '"'

-    * end_quote - the closing quote character. default is '"'

-    * esc_char - the escape character, or None to disable escaping. defualt

-      is "\" (backslash)

-    * encoding - the character encoding (e.g., "utf8"), or None to return

-      raw bytes. defualt is None.

-    * allow_eof - whether to allow EOF before the closing quote is matched.

-      if False, an exception will be raised when EOF is reached by the closing

-      quote is missing. default is False.

-    

-    Example:

-    QuotedString("foo", start_quote = "{", end_quote = "}", esc_char = None)

-    """

-    __slots__ = [

-        "start_quote", "end_quote", "char", "esc_char", "encoding", 

-        "allow_eof"

-    ]

-    def __init__(self, name, start_quote = '"', end_quote = None, 

-                 esc_char = '\\', encoding = None, allow_eof = False):

-        Construct.__init__(self, name)

-        if end_quote is None:

-            end_quote = start_quote

-        self.start_quote = Literal(start_quote)

-        self.char = Char("char")

-        self.end_quote = end_quote

-        self.esc_char = esc_char

-        self.encoding = encoding

-        self.allow_eof = allow_eof

-    

-    def _parse(self, stream, context):

-        self.start_quote._parse(stream, context)

-        text = []

-        escaped = False

-        try:

-            while True:

-                ch = self.char._parse(stream, context)

-                if ch == self.esc_char:

-                    if escaped:

-                        text.append(ch)

-                        escaped = False

-                    else:

-                        escaped = True

-                elif ch == self.end_quote and not escaped:

-                    break

-                else:

-                    text.append(ch)

-                    escaped = False

-        except FieldError:

-            if not self.allow_eof:

-                raise

-        text = "".join(text)

-        if self.encoding is not None:

-            text = text.decode(self.encoding)

-        return text

-    

-    def _build(self, obj, stream, context):

-        self.start_quote._build(None, stream, context)

-        if self.encoding:

-            obj = obj.encode(self.encoding)

-        for ch in obj:

-            if ch == self.esc_char:

-                self.char._build(self.esc_char, stream, context)

-            elif ch == self.end_quote:

-                if self.esc_char is None:

-                    raise QuotedStringError("found ending quote in data, "

-                        "but no escape char defined", ch)

-                else:

-                    self.char._build(self.esc_char, stream, context)

-            self.char._build(ch, stream, context)

-        self.char._build(self.end_quote, stream, context)

-    

-    def _sizeof(self, context):

-        raise SizeofError("can't calculate size")

-

-

-#===============================================================================

-# macros

-#===============================================================================

-class WhitespaceAdapter(Adapter):

-    """

-    Adapter for whitespace sequences; do not use directly.

-    See Whitespace.

-    

-    Parameters:

-    * subcon - the subcon to adapt

-    * build_char - the character used for encoding (building)

-    """

-    __slots__ = ["build_char"]

-    def __init__(self, subcon, build_char):

-        Adapter.__init__(self, subcon)

-        self.build_char = build_char

-    def _encode(self, obj, context):

-        return self.build_char

-    def _decode(self, obj, context):

-        return None

-

-def Whitespace(charset = " \t", optional = True):

-    """whitespace (space that is ignored between tokens). when building, the

-    first character of the charset is used.

-    * charset - the set of characters that are considered whitespace. default

-      is space and tab.

-    * optional - whether or not whitespace is optional. default is True.

-    """

-    con = CharOf(None, charset)

-    if optional:

-        con = OptionalGreedyRange(con)

-    else:

-        con = GreedyRange(con)

-    return WhitespaceAdapter(con, build_char = charset[0])

-

-def Literal(text):

-    """matches a literal string in the text

-    * text - the text (string) to match

-    """

-    return ConstAdapter(Field(None, len(text)), text)

-

-def Char(name):

-    """a one-byte character"""

-    return Field(name, 1)

-

-def CharOf(name, charset):

-    """matches only characters of a given charset

-    * name - the name of the field

-    * charset - the set of valid characters

-    """

-    return OneOf(Char(name), charset)

-

-def CharNoneOf(name, charset):

-    """matches only characters that do not belong to a given charset

-    * name - the name of the field

-    * charset - the set of invalid characters

-    """

-    return NoneOf(Char(name), charset)

-

-def Alpha(name):

-    """a letter character (A-Z, a-z)"""

-    return CharOf(name, set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'))

-

-def Digit(name):

-    """a digit character (0-9)"""

-    return CharOf(name, set('0123456789'))

-

-def AlphaDigit(name):

-    """an alphanumeric character (A-Z, a-z, 0-9)"""

-    return CharOf(name, set("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"))

-

-def BinDigit(name):

-    """a binary digit (0-1)"""

-    return CharOf(name, set('01'))

-

-def HexDigit(name):

-    """a hexadecimal digit (0-9, A-F, a-f)"""

-    return CharOf(name, set('0123456789abcdefABCDEF'))

-

-def Word(name):

-    """a sequence of letters"""

-    return StringAdapter(GreedyRange(Alpha(name)))

-

-class TextualIntAdapter(Adapter):

-    """

-    Adapter for textual integers

-    

-    Parameters:

-    * subcon - the subcon to adapt

-    * radix - the base of the integer (decimal, hexadecimal, binary, ...)

-    * digits - the sequence of digits of that radix

-    """

-    __slots__ = ["radix", "digits"]

-    def __init__(self, subcon, radix = 10, digits = "0123456789abcdef"):

-        Adapter.__init__(self, subcon)

-        if radix > len(digits):

-            raise ValueError("not enough digits for radix %d" % (radix,))

-        self.radix = radix

-        self.digits = digits

-    def _encode(self, obj, context):

-        chars = []

-        if obj < 0:

-            chars.append("-")

-            n = -obj

-        else:

-            n = obj

-        r = self.radix

-        digs = self.digits

-        while n > 0:

-            n, d = divmod(n, r)

-            chars.append(digs[d])

-        # obj2 = "".join(reversed(chars))

-        # filler = digs[0] * (self._sizeof(context) - len(obj2))

-        # return filler + obj2

-        return "".join(reversed(chars))

-    def _decode(self, obj, context):

-        return int("".join(obj), self.radix)

-

-def DecNumber(name):

-    """decimal number"""

-    return TextualIntAdapter(GreedyRange(Digit(name)))

-

-def BinNumber(name):

-    """binary number"""

-    return TextualIntAdapter(GreedyRange(Digit(name)), 2)

-

-def HexNumber(name):

-    """hexadecimal number"""

-    return TextualIntAdapter(GreedyRange(Digit(name)), 16)

-

-def StringUpto(name, charset):

-    """a string that stretches up to a terminator, or EOF. unlike CString, 

-    StringUpto will no consume the terminator char.

-    * name - the name of the field

-    * charset - the set of terminator characters"""

-    return StringAdapter(OptionalGreedyRange(CharNoneOf(name, charset)))

-

-def Line(name):

-    r"""a textual line (up to "\n")"""

-    return StringUpto(name, "\n")

-

-class IdentifierAdapter(Adapter):

-    """

-    Adapter for programmatic identifiers

-    

-    Parameters:

-    * subcon - the subcon to adapt

-    """

-    def _encode(self, obj, context):

-        return obj[0], obj[1:]

-    def _decode(self, obj, context):

-        return obj[0] + "".join(obj[1])

-

-def Identifier(name, 

-               headset = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"), 

-               tailset = set("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_")

-    ):

-    """a programmatic identifier (symbol). must start with a char of headset,

-    followed by a sequence of tailset characters

-    * name - the name of the field

-    * headset - charset for the first character. default is A-Z, a-z, and _

-    * tailset - charset for the tail. default is A-Z, a-z, 0-9 and _

-    """

-    return IdentifierAdapter(

-        Sequence(name,

-            CharOf("head", headset),

-            OptionalGreedyRange(CharOf("tail", tailset)),

-        )

-    )

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

+from core import *
+from adapters import *
+from macros import *
+
+
+#===============================================================================
+# exceptions
+#===============================================================================
+class QuotedStringError(ConstructError):
+    __slots__ = []
+
+
+#===============================================================================
+# constructs
+#===============================================================================
+class QuotedString(Construct):
+    r"""
+    A quoted string (begins with an opening-quote, terminated by a 
+    closing-quote, which may be escaped by an escape character)
+    
+    Parameters:
+    * name - the name of the field
+    * start_quote - the opening quote character. default is '"'
+    * end_quote - the closing quote character. default is '"'
+    * esc_char - the escape character, or None to disable escaping. defualt
+      is "\" (backslash)
+    * encoding - the character encoding (e.g., "utf8"), or None to return
+      raw bytes. defualt is None.
+    * allow_eof - whether to allow EOF before the closing quote is matched.
+      if False, an exception will be raised when EOF is reached by the closing
+      quote is missing. default is False.
+    
+    Example:
+    QuotedString("foo", start_quote = "{", end_quote = "}", esc_char = None)
+    """
+    __slots__ = [
+        "start_quote", "end_quote", "char", "esc_char", "encoding", 
+        "allow_eof"
+    ]
+    def __init__(self, name, start_quote = '"', end_quote = None, 
+                 esc_char = '\\', encoding = None, allow_eof = False):
+        Construct.__init__(self, name)
+        if end_quote is None:
+            end_quote = start_quote
+        self.start_quote = Literal(start_quote)
+        self.char = Char("char")
+        self.end_quote = end_quote
+        self.esc_char = esc_char
+        self.encoding = encoding
+        self.allow_eof = allow_eof
+    
+    def _parse(self, stream, context):
+        self.start_quote._parse(stream, context)
+        text = []
+        escaped = False
+        try:
+            while True:
+                ch = self.char._parse(stream, context)
+                if ch == self.esc_char:
+                    if escaped:
+                        text.append(ch)
+                        escaped = False
+                    else:
+                        escaped = True
+                elif ch == self.end_quote and not escaped:
+                    break
+                else:
+                    text.append(ch)
+                    escaped = False
+        except FieldError:
+            if not self.allow_eof:
+                raise
+        text = "".join(text)
+        if self.encoding is not None:
+            text = text.decode(self.encoding)
+        return text
+    
+    def _build(self, obj, stream, context):
+        self.start_quote._build(None, stream, context)
+        if self.encoding:
+            obj = obj.encode(self.encoding)
+        for ch in obj:
+            if ch == self.esc_char:
+                self.char._build(self.esc_char, stream, context)
+            elif ch == self.end_quote:
+                if self.esc_char is None:
+                    raise QuotedStringError("found ending quote in data, "
+                        "but no escape char defined", ch)
+                else:
+                    self.char._build(self.esc_char, stream, context)
+            self.char._build(ch, stream, context)
+        self.char._build(self.end_quote, stream, context)
+    
+    def _sizeof(self, context):
+        raise SizeofError("can't calculate size")
+
+
+#===============================================================================
+# macros
+#===============================================================================
+class WhitespaceAdapter(Adapter):
+    """
+    Adapter for whitespace sequences; do not use directly.
+    See Whitespace.
+    
+    Parameters:
+    * subcon - the subcon to adapt
+    * build_char - the character used for encoding (building)
+    """
+    __slots__ = ["build_char"]
+    def __init__(self, subcon, build_char):
+        Adapter.__init__(self, subcon)
+        self.build_char = build_char
+    def _encode(self, obj, context):
+        return self.build_char
+    def _decode(self, obj, context):
+        return None
+
+def Whitespace(charset = " \t", optional = True):
+    """whitespace (space that is ignored between tokens). when building, the
+    first character of the charset is used.
+    * charset - the set of characters that are considered whitespace. default
+      is space and tab.
+    * optional - whether or not whitespace is optional. default is True.
+    """
+    con = CharOf(None, charset)
+    if optional:
+        con = OptionalGreedyRange(con)
+    else:
+        con = GreedyRange(con)
+    return WhitespaceAdapter(con, build_char = charset[0])
+
+def Literal(text):
+    """matches a literal string in the text
+    * text - the text (string) to match
+    """
+    return ConstAdapter(Field(None, len(text)), text)
+
+def Char(name):
+    """a one-byte character"""
+    return Field(name, 1)
+
+def CharOf(name, charset):
+    """matches only characters of a given charset
+    * name - the name of the field
+    * charset - the set of valid characters
+    """
+    return OneOf(Char(name), charset)
+
+def CharNoneOf(name, charset):
+    """matches only characters that do not belong to a given charset
+    * name - the name of the field
+    * charset - the set of invalid characters
+    """
+    return NoneOf(Char(name), charset)
+
+def Alpha(name):
+    """a letter character (A-Z, a-z)"""
+    return CharOf(name, set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'))
+
+def Digit(name):
+    """a digit character (0-9)"""
+    return CharOf(name, set('0123456789'))
+
+def AlphaDigit(name):
+    """an alphanumeric character (A-Z, a-z, 0-9)"""
+    return CharOf(name, set("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"))
+
+def BinDigit(name):
+    """a binary digit (0-1)"""
+    return CharOf(name, set('01'))
+
+def HexDigit(name):
+    """a hexadecimal digit (0-9, A-F, a-f)"""
+    return CharOf(name, set('0123456789abcdefABCDEF'))
+
+def Word(name):
+    """a sequence of letters"""
+    return StringAdapter(GreedyRange(Alpha(name)))
+
+class TextualIntAdapter(Adapter):
+    """
+    Adapter for textual integers
+    
+    Parameters:
+    * subcon - the subcon to adapt
+    * radix - the base of the integer (decimal, hexadecimal, binary, ...)
+    * digits - the sequence of digits of that radix
+    """
+    __slots__ = ["radix", "digits"]
+    def __init__(self, subcon, radix = 10, digits = "0123456789abcdef"):
+        Adapter.__init__(self, subcon)
+        if radix > len(digits):
+            raise ValueError("not enough digits for radix %d" % (radix,))
+        self.radix = radix
+        self.digits = digits
+    def _encode(self, obj, context):
+        chars = []
+        if obj < 0:
+            chars.append("-")
+            n = -obj
+        else:
+            n = obj
+        r = self.radix
+        digs = self.digits
+        while n > 0:
+            n, d = divmod(n, r)
+            chars.append(digs[d])
+        # obj2 = "".join(reversed(chars))
+        # filler = digs[0] * (self._sizeof(context) - len(obj2))
+        # return filler + obj2
+        return "".join(reversed(chars))
+    def _decode(self, obj, context):
+        return int("".join(obj), self.radix)
+
+def DecNumber(name):
+    """decimal number"""
+    return TextualIntAdapter(GreedyRange(Digit(name)))
+
+def BinNumber(name):
+    """binary number"""
+    return TextualIntAdapter(GreedyRange(Digit(name)), 2)
+
+def HexNumber(name):
+    """hexadecimal number"""
+    return TextualIntAdapter(GreedyRange(Digit(name)), 16)
+
+def StringUpto(name, charset):
+    """a string that stretches up to a terminator, or EOF. unlike CString, 
+    StringUpto will no consume the terminator char.
+    * name - the name of the field
+    * charset - the set of terminator characters"""
+    return StringAdapter(OptionalGreedyRange(CharNoneOf(name, charset)))
+
+def Line(name):
+    r"""a textual line (up to "\n")"""
+    return StringUpto(name, "\n")
+
+class IdentifierAdapter(Adapter):
+    """
+    Adapter for programmatic identifiers
+    
+    Parameters:
+    * subcon - the subcon to adapt
+    """
+    def _encode(self, obj, context):
+        return obj[0], obj[1:]
+    def _decode(self, obj, context):
+        return obj[0] + "".join(obj[1])
+
+def Identifier(name, 
+               headset = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"), 
+               tailset = set("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_")
+    ):
+    """a programmatic identifier (symbol). must start with a char of headset,
+    followed by a sequence of tailset characters
+    * name - the name of the field
+    * headset - charset for the first character. default is A-Z, a-z, and _
+    * tailset - charset for the tail. default is A-Z, a-z, 0-9 and _
+    """
+    return IdentifierAdapter(
+        Sequence(name,
+            CharOf("head", headset),
+            OptionalGreedyRange(CharOf("tail", tailset)),
+        )
+    )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/elftools/elf/constants.py b/elftools/elf/constants.py
index cd21e09..1d49d2b 100644
--- a/elftools/elf/constants.py
+++ b/elftools/elf/constants.py
@@ -1,46 +1,46 @@
-#-------------------------------------------------------------------------------

-# elftools: elf/constants.py

-#

-# Constants and flags, placed into classes for namespacing

-#

-# Eli Bendersky (eliben@gmail.com)

-# This code is in the public domain

-#-------------------------------------------------------------------------------

-class SHN_INDICES(object):

+#-------------------------------------------------------------------------------
+# elftools: elf/constants.py
+#
+# Constants and flags, placed into classes for namespacing
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+class SHN_INDICES(object):
     """ Special section indices
-    """

-    SHN_UNDEF=0

-    SHN_LORESERVE=0xff00

-    SHN_LOPROC=0xff00

-    SHN_HIPROC=0xff1f

-    SHN_ABS=0xfff1

-    SHN_COMMON=0xfff2

+    """
+    SHN_UNDEF=0
+    SHN_LORESERVE=0xff00
+    SHN_LOPROC=0xff00
+    SHN_HIPROC=0xff1f
+    SHN_ABS=0xfff1
+    SHN_COMMON=0xfff2
     SHN_HIRESERVE=0xffff
-

-

-class SH_FLAGS(object):

+
+
+class SH_FLAGS(object):
     """ Flag values for the sh_flags field of section headers
-    """

-    SHF_WRITE=0x1

-    SHF_ALLOC=0x2

-    SHF_EXECINSTR=0x4

-    SHF_MERGE=0x10

-    SHF_STRINGS=0x20

-    SHF_INFO_LINK=0x40

-    SHF_LINK_ORDER=0x80

-    SHF_OS_NONCONFORMING=0x100

-    SHF_GROUP=0x200

-    SHF_TLS=0x400

-    SHF_MASKOS=0x0ff00000

-    SHF_MASKPROC=0xf0000000

-

-

-class P_FLAGS(object):

+    """
+    SHF_WRITE=0x1
+    SHF_ALLOC=0x2
+    SHF_EXECINSTR=0x4
+    SHF_MERGE=0x10
+    SHF_STRINGS=0x20
+    SHF_INFO_LINK=0x40
+    SHF_LINK_ORDER=0x80
+    SHF_OS_NONCONFORMING=0x100
+    SHF_GROUP=0x200
+    SHF_TLS=0x400
+    SHF_MASKOS=0x0ff00000
+    SHF_MASKPROC=0xf0000000
+
+
+class P_FLAGS(object):
     """ Flag values for the p_flags field of program headers
-    """

-    PF_X=0x1

-    PF_W=0x2

-    PF_R=0x4

-    PF_MASKOS=0x00FF0000

-    PF_MASKPROC=0xFF000000

-

+    """
+    PF_X=0x1
+    PF_W=0x2
+    PF_R=0x4
+    PF_MASKOS=0x00FF0000
+    PF_MASKPROC=0xFF000000
+
diff --git a/elftools/elf/elffile.py b/elftools/elf/elffile.py
index 6f2e723..dc1b246 100644
--- a/elftools/elf/elffile.py
+++ b/elftools/elf/elffile.py
@@ -1,177 +1,177 @@
-#-------------------------------------------------------------------------------

-# elftools: elf/elffile.py

-#

-# ELFFile - main class for accessing ELF files

-#

-# Eli Bendersky (eliben@gmail.com)

-# This code is in the public domain

-#-------------------------------------------------------------------------------

-from ..common.exceptions import ELFError

-from ..common.utils import struct_parse, elf_assert

-from ..construct import ConstructError

-from .structs import ELFStructs

-from .sections import Section, StringTableSection, SymbolTableSection

-from .segments import Segment

-

-

-class ELFFile(object):

-    """ Accessible attributes:

-        

-            elfclass: 

-                32 or 64 - specifies the word size of the target machine

-            

-            little_endian:

-                boolean - specifies the target machine's endianness     

-

-            header:

-                the complete ELF file header

+#-------------------------------------------------------------------------------
+# elftools: elf/elffile.py
+#
+# ELFFile - main class for accessing ELF files
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+from ..common.exceptions import ELFError
+from ..common.utils import struct_parse, elf_assert
+from ..construct import ConstructError
+from .structs import ELFStructs
+from .sections import Section, StringTableSection, SymbolTableSection
+from .segments import Segment
+
+
+class ELFFile(object):
+    """ Accessible attributes:
+        
+            elfclass: 
+                32 or 64 - specifies the word size of the target machine
+            
+            little_endian:
+                boolean - specifies the target machine's endianness     
+
+            header:
+                the complete ELF file header
     """
     def __init__(self, stream):
-        self.stream = stream

-        self._identify_file()

-        self.structs = ELFStructs(

-            little_endian=self.little_endian,

-            elfclass=self.elfclass)

-        self.header = self._parse_elf_header()

-        

-        self._file_stringtable_section = self._get_file_stringtable()

-    

+        self.stream = stream
+        self._identify_file()
+        self.structs = ELFStructs(
+            little_endian=self.little_endian,
+            elfclass=self.elfclass)
+        self.header = self._parse_elf_header()
+        
+        self._file_stringtable_section = self._get_file_stringtable()
+    
     def num_sections(self):
         """ Number of sections in the file
-        """

-        return self['e_shnum']

-    

+        """
+        return self['e_shnum']
+    
     def get_section(self, n):
-        """ Get the section at index #n from the file (Section object or a

+        """ Get the section at index #n from the file (Section object or a
             subclass)
-        """

-        section_header = self._get_section_header(n)

-        return self._make_section(section_header)

-    

+        """
+        section_header = self._get_section_header(n)
+        return self._make_section(section_header)
+    
     def iter_sections(self):
         """ Yield all the sections in the file
-        """

-        for i in range(self.num_sections()):

-            yield self.get_section(i)

-    

+        """
+        for i in range(self.num_sections()):
+            yield self.get_section(i)
+    
     def num_segments(self):
         """ Number of segments in the file
-        """

-        return self['e_phnum']

-    

+        """
+        return self['e_phnum']
+    
     def get_segment(self, n):
         """ Get the segment at index #n from the file (Segment object)
-        """

-        segment_header = self._get_segment_header(n)

-        return Segment(segment_header, self.stream)

-    

+        """
+        segment_header = self._get_segment_header(n)
+        return Segment(segment_header, self.stream)
+    
     def iter_segments(self):
         """ Yield all the segments in the file
-        """

-        for i in range(self.num_segments()):

-            yield self.get_segment(i)

-    

-    #-------------------------------- PRIVATE --------------------------------#

-    

+        """
+        for i in range(self.num_segments()):
+            yield self.get_segment(i)
+    
+    #-------------------------------- PRIVATE --------------------------------#
+    
     def __getitem__(self, name):
         """ Implement dict-like access to header entries
-        """

-        return self.header[name]

-        

+        """
+        return self.header[name]
+        
     def _identify_file(self):
         """ Verify the ELF file and identify its class and endianness.
-        """

-        # Note: this code reads the stream directly, without using ELFStructs,

-        # since we don't yet know its exact format. ELF was designed to be 

-        # read like this - its e_ident field is word-size and endian agnostic.

-        #

-        self.stream.seek(0)

-        magic = self.stream.read(4)

-        elf_assert(magic == '\x7fELF', 'Magic number does not match')

-        

-        ei_class = self.stream.read(1)

-        if ei_class == '\x01':

-            self.elfclass = 32

-        elif ei_class == '\x02':

-            self.elfclass = 64

-        else:

-            raise ELFError('Invalid EI_CLASS %s' % repr(ei_class))

-        

-        ei_data = self.stream.read(1)

-        if ei_data == '\x01':

-            self.little_endian = True

-        elif ei_data == '\x02':

-            self.little_endian = False

-        else:

-            raise ELFError('Invalid EI_DATA %s' % repr(ei_data))

-    

+        """
+        # Note: this code reads the stream directly, without using ELFStructs,
+        # since we don't yet know its exact format. ELF was designed to be 
+        # read like this - its e_ident field is word-size and endian agnostic.
+        #
+        self.stream.seek(0)
+        magic = self.stream.read(4)
+        elf_assert(magic == '\x7fELF', 'Magic number does not match')
+        
+        ei_class = self.stream.read(1)
+        if ei_class == '\x01':
+            self.elfclass = 32
+        elif ei_class == '\x02':
+            self.elfclass = 64
+        else:
+            raise ELFError('Invalid EI_CLASS %s' % repr(ei_class))
+        
+        ei_data = self.stream.read(1)
+        if ei_data == '\x01':
+            self.little_endian = True
+        elif ei_data == '\x02':
+            self.little_endian = False
+        else:
+            raise ELFError('Invalid EI_DATA %s' % repr(ei_data))
+    
     def _section_offset(self, n):
         """ Compute the offset of section #n in the file
-        """

-        return self['e_shoff'] + n * self['e_shentsize']

-    

+        """
+        return self['e_shoff'] + n * self['e_shentsize']
+    
     def _segment_offset(self, n):
         """ Compute the offset of segment #n in the file
-        """

-        return self['e_phoff'] + n * self['e_phentsize']

-    

+        """
+        return self['e_phoff'] + n * self['e_phentsize']
+    
     def _get_section_header(self, n):
         """ Find the header of section #n, parse it and return the struct 
-        """

-        return struct_parse(

-            self.structs.Elf_Shdr,

-            self.stream,

-            stream_pos=self._section_offset(n))

-    

-    def _get_section_name(self, section_header):

-        """ Given a section header, find this section's name in the file's

-            string table

-        """

-        name_offset = section_header['sh_name']

-        return self._file_stringtable_section.get_string(name_offset)

-

+        """
+        return struct_parse(
+            self.structs.Elf_Shdr,
+            self.stream,
+            stream_pos=self._section_offset(n))
+    
+    def _get_section_name(self, section_header):
+        """ Given a section header, find this section's name in the file's
+            string table
+        """
+        name_offset = section_header['sh_name']
+        return self._file_stringtable_section.get_string(name_offset)
+
     def _make_section(self, section_header):
         """ Create a section object of the appropriate type
-        """

-        name = self._get_section_name(section_header)

-        sectype = section_header['sh_type']

-        

-        if sectype == 'SHT_STRTAB':

-            return StringTableSection(section_header, name, self.stream)

-        elif sectype in ('SHT_SYMTAB', 'SHT_DYNSYM'):

-            return self._make_symbol_table_section(section_header, name)

-        else:

-            return Section(section_header, name, self.stream)

-

+        """
+        name = self._get_section_name(section_header)
+        sectype = section_header['sh_type']
+        
+        if sectype == 'SHT_STRTAB':
+            return StringTableSection(section_header, name, self.stream)
+        elif sectype in ('SHT_SYMTAB', 'SHT_DYNSYM'):
+            return self._make_symbol_table_section(section_header, name)
+        else:
+            return Section(section_header, name, self.stream)
+
     def _make_symbol_table_section(self, section_header, name):
         """ Create a SymbolTableSection
-        """

-        linked_strtab_index = section_header['sh_link']

-        strtab_section = self.get_section(linked_strtab_index)

-        return SymbolTableSection(

-            section_header, name, self.stream,

-            stringtable=strtab_section)

-

+        """
+        linked_strtab_index = section_header['sh_link']
+        strtab_section = self.get_section(linked_strtab_index)
+        return SymbolTableSection(
+            section_header, name, self.stream,
+            stringtable=strtab_section)
+
     def _get_segment_header(self, n):
         """ Find the header of segment #n, parse it and return the struct
-        """

-        return struct_parse(

-            self.structs.Elf_Phdr,

-            self.stream,

-            stream_pos=self._segment_offset(n))

-    

+        """
+        return struct_parse(
+            self.structs.Elf_Phdr,
+            self.stream,
+            stream_pos=self._segment_offset(n))
+    
     def _get_file_stringtable(self):
         """ Find the file's string table section
-        """

-        stringtable_section_num = self['e_shstrndx']

-        return StringTableSection(

-                header=self._get_section_header(stringtable_section_num),

-                name='',

-                stream=self.stream)

-    

+        """
+        stringtable_section_num = self['e_shstrndx']
+        return StringTableSection(
+                header=self._get_section_header(stringtable_section_num),
+                name='',
+                stream=self.stream)
+    
     def _parse_elf_header(self):
-        """ Parses the ELF file header and assigns the result to attributes

+        """ Parses the ELF file header and assigns the result to attributes
             of this object.
-        """

-        return struct_parse(self.structs.Elf_Ehdr, self.stream, stream_pos=0)

-

+        """
+        return struct_parse(self.structs.Elf_Ehdr, self.stream, stream_pos=0)
+
diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py
index cdaf316..31647ac 100644
--- a/elftools/elf/enums.py
+++ b/elftools/elf/enums.py
@@ -1,107 +1,107 @@
-#-------------------------------------------------------------------------------

-# elftools: elf/enums.py

-#

-# Mappings of enum names to values

-#

-# Eli Bendersky (eliben@gmail.com)

-# This code is in the public domain

-#-------------------------------------------------------------------------------

-

-# e_ident[EI_CLASS] in the ELF header

-ENUM_EI_CLASS = dict(

-    ELFCLASSNONE=0,

-    ELFCLASS32=1,

-    ELFCLASS64=2

-)

-

-# e_ident[EI_DATA] in the ELF header

-ENUM_EI_DATA = dict(

-    ELFDATANONE=0,

-    ELFDATA2LSB=1,

-    ELFDATA2MSB=2

-)

-

-# e_version in the ELF header

-ENUM_E_VERSION = dict(

-    EV_NONE=0,

-    EV_CURRENT=1

-)

-

-# e_type in the ELF header

-ENUM_E_TYPE = dict(

-    ET_NONE=0,

-    ET_REL=1,

-    ET_EXEC=2,

-    ET_DYN=3,

-    ET_CORE=4,

-    ET_LOPROC=0xff00,

-    ET_HIPROC=0xffff,

-    _default_='PROC_SPECIFIC',

-)

-

-# e_machine in the ELF header

-# (this list is currently somewhat partial...)

-ENUM_E_MACHINE = dict(

-    EM_NONE=0,

-    EM_M32=1,

-    EM_SPARC=2,

-    EM_386=3,

-    EM_68K=4,

-    EM_88K=5,

-    EM_860=7,

-    EM_MIPS=8,

-    EM_S370=9,

-    EM_MIPS_RS4_BE=10,

-    EM_IA_64=50,

-    EM_X86_64=62,

-    EM_AVR=83,

-    _default_='RESERVED',

-)

-

-# sh_type in the section header

-ENUM_SH_TYPE = dict(

-    SHT_NULL=0,

-    SHT_PROGBITS=1,

-    SHT_SYMTAB=2,

-    SHT_STRTAB=3,

-    SHT_RELA=4,

-    SHT_HASH=5,

-    SHT_DYNAMIC=6,

-    SHT_NOTE=7,

-    SHT_NOBITS=8,

-    SHT_REL=9,

-    SHT_SHLIB=10,

-    SHT_DYNSYM=11,

-    SHT_INIT_ARRAY=14,

-    SHT_FINI_ARRAY=15,

-    SHT_PREINIT_ARRAY=16,

-    SHT_GROUP=17,

-    SHT_SYMTAB_SHNDX=18,

-    SHT_NUM=19,

-    SHT_LOOS=0x60000000,

-    SHT_HIOS=0x6fffffff,

-    SHT_LOPROC=0x70000000,

-    SHT_HIPROC=0x7fffffff,

-    SHT_LOUSER=0x80000000,

-    SHT_HIUSER=0xffffffff,

-    SHT_AMD64_UNWIND=0x70000001,

-    _default_='RESERVED',

-)

-

-# p_type in the program header

-# some values scavenged from the ELF headers in binutils-2.21

-ENUM_P_TYPE = dict(

-    PT_NULL=0,

-    PT_LOAD=1,

-    PT_DYNAMIC=2,

-    PT_INTERP=3,

-    PT_NOTE=4,

-    PT_SHLIB=5,

-    PT_PHDR=6,

-    PT_LOPROC=0x70000000,

-    PT_HIPROC=0x7fffffff,

-    PT_GNU_EH_FRAME=0x6474e550,

-    PT_GNU_STACK=0x6474e551,

-    PT_GNU_RELRO=0x6474e552,

-)

-

+#-------------------------------------------------------------------------------
+# elftools: elf/enums.py
+#
+# Mappings of enum names to values
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+
+# e_ident[EI_CLASS] in the ELF header
+ENUM_EI_CLASS = dict(
+    ELFCLASSNONE=0,
+    ELFCLASS32=1,
+    ELFCLASS64=2
+)
+
+# e_ident[EI_DATA] in the ELF header
+ENUM_EI_DATA = dict(
+    ELFDATANONE=0,
+    ELFDATA2LSB=1,
+    ELFDATA2MSB=2
+)
+
+# e_version in the ELF header
+ENUM_E_VERSION = dict(
+    EV_NONE=0,
+    EV_CURRENT=1
+)
+
+# e_type in the ELF header
+ENUM_E_TYPE = dict(
+    ET_NONE=0,
+    ET_REL=1,
+    ET_EXEC=2,
+    ET_DYN=3,
+    ET_CORE=4,
+    ET_LOPROC=0xff00,
+    ET_HIPROC=0xffff,
+    _default_='PROC_SPECIFIC',
+)
+
+# e_machine in the ELF header
+# (this list is currently somewhat partial...)
+ENUM_E_MACHINE = dict(
+    EM_NONE=0,
+    EM_M32=1,
+    EM_SPARC=2,
+    EM_386=3,
+    EM_68K=4,
+    EM_88K=5,
+    EM_860=7,
+    EM_MIPS=8,
+    EM_S370=9,
+    EM_MIPS_RS4_BE=10,
+    EM_IA_64=50,
+    EM_X86_64=62,
+    EM_AVR=83,
+    _default_='RESERVED',
+)
+
+# sh_type in the section header
+ENUM_SH_TYPE = dict(
+    SHT_NULL=0,
+    SHT_PROGBITS=1,
+    SHT_SYMTAB=2,
+    SHT_STRTAB=3,
+    SHT_RELA=4,
+    SHT_HASH=5,
+    SHT_DYNAMIC=6,
+    SHT_NOTE=7,
+    SHT_NOBITS=8,
+    SHT_REL=9,
+    SHT_SHLIB=10,
+    SHT_DYNSYM=11,
+    SHT_INIT_ARRAY=14,
+    SHT_FINI_ARRAY=15,
+    SHT_PREINIT_ARRAY=16,
+    SHT_GROUP=17,
+    SHT_SYMTAB_SHNDX=18,
+    SHT_NUM=19,
+    SHT_LOOS=0x60000000,
+    SHT_HIOS=0x6fffffff,
+    SHT_LOPROC=0x70000000,
+    SHT_HIPROC=0x7fffffff,
+    SHT_LOUSER=0x80000000,
+    SHT_HIUSER=0xffffffff,
+    SHT_AMD64_UNWIND=0x70000001,
+    _default_='RESERVED',
+)
+
+# p_type in the program header
+# some values scavenged from the ELF headers in binutils-2.21
+ENUM_P_TYPE = dict(
+    PT_NULL=0,
+    PT_LOAD=1,
+    PT_DYNAMIC=2,
+    PT_INTERP=3,
+    PT_NOTE=4,
+    PT_SHLIB=5,
+    PT_PHDR=6,
+    PT_LOPROC=0x70000000,
+    PT_HIPROC=0x7fffffff,
+    PT_GNU_EH_FRAME=0x6474e550,
+    PT_GNU_STACK=0x6474e551,
+    PT_GNU_RELRO=0x6474e552,
+)
+
diff --git a/elftools/elf/sections.py b/elftools/elf/sections.py
index 6accf11..04410f3 100644
--- a/elftools/elf/sections.py
+++ b/elftools/elf/sections.py
@@ -1,60 +1,60 @@
-#-------------------------------------------------------------------------------

-# elftools: elf/sections.py

-#

-# ELF sections

-#

-# Eli Bendersky (eliben@gmail.com)

-# This code is in the public domain

-#-------------------------------------------------------------------------------

-from ..construct import CString

-from ..common.utils import struct_parse, elf_assert

-

-

-class Section(object):

-    """ Base class for ELF sections. Also used for all sections types that have

-        no special functionality.

-        

-        Allows dictionary-like access to the section header. For example:

-         > sec = Section(...)

-         > sec['sh_type']  # section type

+#-------------------------------------------------------------------------------
+# elftools: elf/sections.py
+#
+# ELF sections
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+from ..construct import CString
+from ..common.utils import struct_parse, elf_assert
+
+
+class Section(object):
+    """ Base class for ELF sections. Also used for all sections types that have
+        no special functionality.
+        
+        Allows dictionary-like access to the section header. For example:
+         > sec = Section(...)
+         > sec['sh_type']  # section type
     """
     def __init__(self, header, name, stream):
-        self.header = header

-        self.name = name

-        self.stream = stream

-    

+        self.header = header
+        self.name = name
+        self.stream = stream
+    
     def data(self):
         """ The section data from the file.
-        """

-        self.stream.seek(self['sh_offset'])

+        """
+        self.stream.seek(self['sh_offset'])
         return self.stream.read(self['sh_size'])
-

-    def __getitem__(self, name):

-        """ Implement dict-like access to header entries

-        """

-        return self.header[name]

-

-

-class StringTableSection(Section):

+
+    def __getitem__(self, name):
+        """ Implement dict-like access to header entries
+        """
+        return self.header[name]
+
+
+class StringTableSection(Section):
     """ ELF string table section.
     """
     def __init__(self, header, name, stream):
-        super(StringTableSection, self).__init__(header, name, stream)

-        

-    def get_string(self, offset):

+        super(StringTableSection, self).__init__(header, name, stream)
+        
+    def get_string(self, offset):
         """ Get the string stored at the given offset in this string table.
-        """

-        table_offset = self['sh_offset']

-        return struct_parse(

-            CString(''),

-            self.stream,

-            stream_pos=table_offset + offset)

-

-

-class SymbolTableSection(Section):

-    """ ELF symbol table section. Has an associated StringTableSection that's

+        """
+        table_offset = self['sh_offset']
+        return struct_parse(
+            CString(''),
+            self.stream,
+            stream_pos=table_offset + offset)
+
+
+class SymbolTableSection(Section):
+    """ ELF symbol table section. Has an associated StringTableSection that's
         passed in the constructor.
     """
-    def __init__(self, header, name, stream, stringtable):

+    def __init__(self, header, name, stream, stringtable):
         super(SymbolTableSection, self).__init__(header, name, stream)
-        self.stringtable = stringtable

+        self.stringtable = stringtable
diff --git a/elftools/elf/segments.py b/elftools/elf/segments.py
index 02a81ed..a583de0 100644
--- a/elftools/elf/segments.py
+++ b/elftools/elf/segments.py
@@ -1,25 +1,25 @@
-#-------------------------------------------------------------------------------

-# elftools: elf/segments.py

-#

-# ELF segments

-#

-# Eli Bendersky (eliben@gmail.com)

-# This code is in the public domain

-#-------------------------------------------------------------------------------

-

-class Segment(object):

-    def __init__(self, header, stream):

-        self.header = header

-        self.stream = stream

-    

-    def data(self):

-        """ The segment data from the file.

-        """

-        self.stream.seek(self['p_offset'])

-        return self.stream.read(self['p_filesz'])

-

-    def __getitem__(self, name):

-        """ Implement dict-like access to header entries

-        """

-        return self.header[name]

-

+#-------------------------------------------------------------------------------
+# elftools: elf/segments.py
+#
+# ELF segments
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+
+class Segment(object):
+    def __init__(self, header, stream):
+        self.header = header
+        self.stream = stream
+    
+    def data(self):
+        """ The segment data from the file.
+        """
+        self.stream.seek(self['p_offset'])
+        return self.stream.read(self['p_filesz'])
+
+    def __getitem__(self, name):
+        """ Implement dict-like access to header entries
+        """
+        return self.header[name]
+
diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py
index 465a9c8..c628c93 100644
--- a/elftools/elf/structs.py
+++ b/elftools/elf/structs.py
@@ -1,153 +1,153 @@
-#-------------------------------------------------------------------------------

-# elftools: elf/structs.py

-#

-# Encapsulation of Construct structs for parsing an ELF file, adjusted for

-# correct endianness and word-size.

-#

-# Eli Bendersky (eliben@gmail.com)

-# This code is in the public domain

-#-------------------------------------------------------------------------------

-from ..construct import (

-    UBInt8, UBInt16, UBInt32, UBInt64,

-    ULInt8, ULInt16, ULInt32, ULInt64,

-    SBInt32, SLInt32, SBInt64, SLInt64,

-    Struct, Array, Enum, Padding,

-    )

-

-from .enums import *

-

-

-class ELFStructs(object):

-    """ Accessible attributes:

-    

-            Elf_{byte|half|word|addr|offset|sword|xword|xsword}:

-                Data chunks, as specified by the ELF standard, adjusted for 

-                correct endianness and word-size.

-            

-            Elf_Ehdr:

-                ELF file header

-            

-            Elf_Phdr:

-                Program header

-            

-            Elf_Shdr:

-                Section header

-            

-            Elf_Sym:

+#-------------------------------------------------------------------------------
+# elftools: elf/structs.py
+#
+# Encapsulation of Construct structs for parsing an ELF file, adjusted for
+# correct endianness and word-size.
+#
+# Eli Bendersky (eliben@gmail.com)
+# This code is in the public domain
+#-------------------------------------------------------------------------------
+from ..construct import (
+    UBInt8, UBInt16, UBInt32, UBInt64,
+    ULInt8, ULInt16, ULInt32, ULInt64,
+    SBInt32, SLInt32, SBInt64, SLInt64,
+    Struct, Array, Enum, Padding,
+    )
+
+from .enums import *
+
+
+class ELFStructs(object):
+    """ Accessible attributes:
+    
+            Elf_{byte|half|word|addr|offset|sword|xword|xsword}:
+                Data chunks, as specified by the ELF standard, adjusted for 
+                correct endianness and word-size.
+            
+            Elf_Ehdr:
+                ELF file header
+            
+            Elf_Phdr:
+                Program header
+            
+            Elf_Shdr:
+                Section header
+            
+            Elf_Sym:
                 Symbol table entry
     """
-    def __init__(self, little_endian=True, elfclass=32):

-        assert elfclass == 32 or elfclass == 64

-        self.little_endian = little_endian

-        self.elfclass = elfclass        

-        self._create_structs()

-    

+    def __init__(self, little_endian=True, elfclass=32):
+        assert elfclass == 32 or elfclass == 64
+        self.little_endian = little_endian
+        self.elfclass = elfclass        
+        self._create_structs()
+    
     def _create_structs(self):
-        if self.little_endian:

-            self.Elf_byte = ULInt8

-            self.Elf_half = ULInt16

-            self.Elf_word = ULInt32

-            self.Elf_addr = ULInt32 if self.elfclass == 32 else ULInt64

-            self.Elf_offset = self.Elf_addr

-            self.Elf_sword = SLInt32

-            self.Elf_xword = ULInt32 if self.elfclass == 32 else ULInt64

-            self.Elf_sxword = SLInt32 if self.elfclass == 32 else SLInt64

-        else:

-            self.Elf_byte = UBInt8

-            self.Elf_half = UBInt16

-            self.Elf_word = UBInt32

-            self.Elf_addr = UBInt32 if self.elfclass == 32 else UBInt64

-            self.Elf_offset = self.Elf_addr

-            self.Elf_sword = SBInt32

-            self.Elf_xword = UBInt32 if self.elfclass == 32 else UBInt64

-            self.Elf_sxword = SBInt32 if self.elfclass == 32 else SBInt64

-        

-        self._create_ehdr()

-        self._create_phdr()

-        self._create_shdr()

-        self._create_sym()

-    

+        if self.little_endian:
+            self.Elf_byte = ULInt8
+            self.Elf_half = ULInt16
+            self.Elf_word = ULInt32
+            self.Elf_addr = ULInt32 if self.elfclass == 32 else ULInt64
+            self.Elf_offset = self.Elf_addr
+            self.Elf_sword = SLInt32
+            self.Elf_xword = ULInt32 if self.elfclass == 32 else ULInt64
+            self.Elf_sxword = SLInt32 if self.elfclass == 32 else SLInt64
+        else:
+            self.Elf_byte = UBInt8
+            self.Elf_half = UBInt16
+            self.Elf_word = UBInt32
+            self.Elf_addr = UBInt32 if self.elfclass == 32 else UBInt64
+            self.Elf_offset = self.Elf_addr
+            self.Elf_sword = SBInt32
+            self.Elf_xword = UBInt32 if self.elfclass == 32 else UBInt64
+            self.Elf_sxword = SBInt32 if self.elfclass == 32 else SBInt64
+        
+        self._create_ehdr()
+        self._create_phdr()
+        self._create_shdr()
+        self._create_sym()
+    
     def _create_ehdr(self):
-        self.Elf_Ehdr = Struct('Elf_Ehdr',

-            Struct('e_ident',

-                Array(4, self.Elf_byte('EI_MAG')),

-                Enum(self.Elf_byte('EI_CLASS'), **ENUM_EI_CLASS),

-                Enum(self.Elf_byte('EI_DATA'), **ENUM_EI_DATA),

-                Enum(self.Elf_byte('EI_VERSION'), **ENUM_E_VERSION),

-                Padding(9)                

-            ),

-            Enum(self.Elf_half('e_type'), **ENUM_E_TYPE),

-            Enum(self.Elf_half('e_machine'), **ENUM_E_MACHINE),

-            Enum(self.Elf_word('e_version'), **ENUM_E_VERSION),

-            self.Elf_addr('e_entry'),

-            self.Elf_offset('e_phoff'),

-            self.Elf_offset('e_shoff'),

-            self.Elf_word('e_flags'),

-            self.Elf_half('e_ehsize'),

-            self.Elf_half('e_phentsize'),

-            self.Elf_half('e_phnum'),

-            self.Elf_half('e_shentsize'),

-            self.Elf_half('e_shnum'),

-            self.Elf_half('e_shstrndx'),

-        )

-    

-    def _create_phdr(self):

-        if self.elfclass == 32:

-            self.Elf_Phdr = Struct('Elf_Phdr',

-                Enum(self.Elf_word('p_type'), **ENUM_P_TYPE),

-                self.Elf_offset('p_offset'),

-                self.Elf_addr('p_vaddr'),

-                self.Elf_addr('p_paddr'),

-                self.Elf_word('p_filesz'),

-                self.Elf_word('p_memsz'),

-                self.Elf_word('p_flags'),

-                self.Elf_word('p_align'),

-            )

-        else:

-            self.Elf_Phdr = Struct('Elf_Phdr',

-                Enum(self.Elf_word('p_type'), **ENUM_P_TYPE),

-                self.Elf_word('p_flags'),

-                self.Elf_offset('p_offset'),

-                self.Elf_addr('p_vaddr'),

-                self.Elf_addr('p_paddr'),

-                self.Elf_word('p_filesz'),

-                self.Elf_word('p_memsz'),

-                self.Elf_word('p_align'),

-            )   

-        

+        self.Elf_Ehdr = Struct('Elf_Ehdr',
+            Struct('e_ident',
+                Array(4, self.Elf_byte('EI_MAG')),
+                Enum(self.Elf_byte('EI_CLASS'), **ENUM_EI_CLASS),
+                Enum(self.Elf_byte('EI_DATA'), **ENUM_EI_DATA),
+                Enum(self.Elf_byte('EI_VERSION'), **ENUM_E_VERSION),
+                Padding(9)                
+            ),
+            Enum(self.Elf_half('e_type'), **ENUM_E_TYPE),
+            Enum(self.Elf_half('e_machine'), **ENUM_E_MACHINE),
+            Enum(self.Elf_word('e_version'), **ENUM_E_VERSION),
+            self.Elf_addr('e_entry'),
+            self.Elf_offset('e_phoff'),
+            self.Elf_offset('e_shoff'),
+            self.Elf_word('e_flags'),
+            self.Elf_half('e_ehsize'),
+            self.Elf_half('e_phentsize'),
+            self.Elf_half('e_phnum'),
+            self.Elf_half('e_shentsize'),
+            self.Elf_half('e_shnum'),
+            self.Elf_half('e_shstrndx'),
+        )
+    
+    def _create_phdr(self):
+        if self.elfclass == 32:
+            self.Elf_Phdr = Struct('Elf_Phdr',
+                Enum(self.Elf_word('p_type'), **ENUM_P_TYPE),
+                self.Elf_offset('p_offset'),
+                self.Elf_addr('p_vaddr'),
+                self.Elf_addr('p_paddr'),
+                self.Elf_word('p_filesz'),
+                self.Elf_word('p_memsz'),
+                self.Elf_word('p_flags'),
+                self.Elf_word('p_align'),
+            )
+        else:
+            self.Elf_Phdr = Struct('Elf_Phdr',
+                Enum(self.Elf_word('p_type'), **ENUM_P_TYPE),
+                self.Elf_word('p_flags'),
+                self.Elf_offset('p_offset'),
+                self.Elf_addr('p_vaddr'),
+                self.Elf_addr('p_paddr'),
+                self.Elf_word('p_filesz'),
+                self.Elf_word('p_memsz'),
+                self.Elf_word('p_align'),
+            )   
+        
     def _create_shdr(self):
-        self.Elf_Shdr = Struct('Elf_Shdr',

-            self.Elf_word('sh_name'),

-            Enum(self.Elf_word('sh_type'), **ENUM_SH_TYPE),

-            self.Elf_xword('sh_flags'),

-            self.Elf_addr('sh_addr'),

-            self.Elf_offset('sh_offset'),

-            self.Elf_xword('sh_size'),

-            self.Elf_word('sh_link'),

-            self.Elf_word('sh_info'),

-            self.Elf_xword('sh_addralign'),

-            self.Elf_xword('sh_entsize'),

-        )

-    

+        self.Elf_Shdr = Struct('Elf_Shdr',
+            self.Elf_word('sh_name'),
+            Enum(self.Elf_word('sh_type'), **ENUM_SH_TYPE),
+            self.Elf_xword('sh_flags'),
+            self.Elf_addr('sh_addr'),
+            self.Elf_offset('sh_offset'),
+            self.Elf_xword('sh_size'),
+            self.Elf_word('sh_link'),
+            self.Elf_word('sh_info'),
+            self.Elf_xword('sh_addralign'),
+            self.Elf_xword('sh_entsize'),
+        )
+    
     def _create_sym(self):
-        if self.elfclass == 32:

-            self.Elf_Sym = Struct('Elf_Sym',

-                self.Elf_word('st_name'),

-                self.Elf_addr('st_value'),

-                self.Elf_word('st_size'),

-                self.Elf_byte('st_info'),

-                self.Elf_byte('st_other'),

-                self.Elf_half('st_shndx'),

-            )

-        else:

-            self.Elf_Sym = Struct('Elf_Sym',

-                self.Elf_word('st_name'),

-                self.Elf_byte('st_info'),

-                self.Elf_byte('st_other'),

-                self.Elf_half('st_shndx'),

-                self.Elf_addr('st_value'),

-                self.Elf_xword('st_size'),

-            )

-

-

-

+        if self.elfclass == 32:
+            self.Elf_Sym = Struct('Elf_Sym',
+                self.Elf_word('st_name'),
+                self.Elf_addr('st_value'),
+                self.Elf_word('st_size'),
+                self.Elf_byte('st_info'),
+                self.Elf_byte('st_other'),
+                self.Elf_half('st_shndx'),
+            )
+        else:
+            self.Elf_Sym = Struct('Elf_Sym',
+                self.Elf_word('st_name'),
+                self.Elf_byte('st_info'),
+                self.Elf_byte('st_other'),
+                self.Elf_half('st_shndx'),
+                self.Elf_addr('st_value'),
+                self.Elf_xword('st_size'),
+            )
+
+
+
diff --git a/z.py b/z.py
index 2a5485c..fc295e7 100644
--- a/z.py
+++ b/z.py
@@ -1,57 +1,58 @@
-import sys

-from elftools.elf.structs import ELFStructs

-from elftools.elf.elffile import ELFFile

-from elftools.elf.sections import *

-

-# read a little-endian, 64-bit file

-es = ELFStructs(True, 64)

-

-stream = open('binfiles/z.elf', 'rb')

-

-efile = ELFFile(stream)

-

-print '===> %s sections!' % efile.num_sections() 

-print '===> %s segments!' % efile.num_segments()

-

-for sec in efile.iter_sections():

-    print type(sec), sec.name

-    if isinstance(sec, SymbolTableSection):

-        print '   linked string table:', sec.stringtable.name

-

-for seg in efile.iter_segments():

-    print seg['p_type'], seg['p_offset']

-

-

-#~ print 'num', efile.num_sections()

-#~ sec = efile.get_section(39)

-#~ print sec.header

-#~ print sec.name

-#~ print sec['sh_type']

-#~ print map(ord, sec.data())

-

-#~ print sec.stream

-#~ print map(ord, efile._stringtable)

-

-#~ print efile.header

-#~ print dir(efile)

-#~ print efile['e_type']

-

-#~ shtable_offset = efile['e_shoff']

-#~ strtable_section_offset = shtable_offset + efile['e_shstrndx'] * efile['e_shentsize']

-

-#~ # get to the section header for the sh string table

-#~ print strtable_section_offset

-#~ stream.seek(strtable_section_offset)

-#~ sheader = es.Elf_Shdr.parse_stream(stream)

-#~ print sheader

-

-#~ # yay, looks correct!!

-#~ stream.seek(sheader.sh_offset)

-#~ buf = stream.read(sheader.sh_size)

-#~ for c in buf:

-    #~ sys.stdout.write('%02X' % ord(c))

-

-

-

-

-#~ print es.Elf_Ehdr

+import sys
+from elftools.elf.structs import ELFStructs
+from elftools.elf.elffile import ELFFile
+from elftools.elf.sections import *
+
+# read a little-endian, 64-bit file
+es = ELFStructs(True, 64)
+
+stream = open('binfiles/z.elf', 'rb')
+#stream = open('binfiles/z32.elf', 'rb')
+
+efile = ELFFile(stream)
+
+print '===> %s sections!' % efile.num_sections() 
+print '===> %s segments!' % efile.num_segments()
+
+for sec in efile.iter_sections():
+    print type(sec), sec.name
+    if isinstance(sec, SymbolTableSection):
+        print '   linked string table:', sec.stringtable.name
+
+for seg in efile.iter_segments():
+    print seg['p_type'], seg['p_offset']
+
+
+#~ print 'num', efile.num_sections()
+#~ sec = efile.get_section(39)
+#~ print sec.header
+#~ print sec.name
+#~ print sec['sh_type']
+#~ print map(ord, sec.data())
+
+#~ print sec.stream
+#~ print map(ord, efile._stringtable)
+
+#~ print efile.header
+#~ print dir(efile)
+#~ print efile['e_type']
+
+#~ shtable_offset = efile['e_shoff']
+#~ strtable_section_offset = shtable_offset + efile['e_shstrndx'] * efile['e_shentsize']
+
+#~ # get to the section header for the sh string table
+#~ print strtable_section_offset
+#~ stream.seek(strtable_section_offset)
+#~ sheader = es.Elf_Shdr.parse_stream(stream)
+#~ print sheader
+
+#~ # yay, looks correct!!
+#~ stream.seek(sheader.sh_offset)
+#~ buf = stream.read(sheader.sh_size)
+#~ for c in buf:
+    #~ sys.stdout.write('%02X' % ord(c))
+
+
+
+
+#~ print es.Elf_Ehdr