More complete handling of constant field length expressions.
authorRichard W.M. Jones <rich@annexia.org>
Sun, 18 May 2008 15:39:29 +0000 (15:39 +0000)
committerRichard W.M. Jones <rich@annexia.org>
Sun, 18 May 2008 15:39:29 +0000 (15:39 +0000)
More TODO line items.
Set svnignore and remove old cvsignore file.
Fix link to bitmatch home page.

.cvsignore [deleted file]
TODO
bitmatch.mli
pa_bitmatch.ml

diff --git a/.cvsignore b/.cvsignore
deleted file mode 100644 (file)
index 3e76a87..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-*.cmi
-*.cmo
-*.cmx
-*.cma
-*.cmxa
-ocaml-bitmatch-*.tar.gz
-Makefile
-META
-configure
-autom4te.cache
-config.h.in
-config.h
-config.log
-config.status
-html
diff --git a/TODO b/TODO
index 10ea7a9..ecb0620 100644 (file)
--- a/TODO
+++ b/TODO
@@ -35,3 +35,24 @@ Major to-do items.
 
 (10) Cross-module, persistent, named patterns, see:
   http://caml.inria.fr/pub/ml-archives/caml-list/2008/04/25992c9c9fa999fe1d35d961dd9917a2.en.html
 
 (10) Cross-module, persistent, named patterns, see:
   http://caml.inria.fr/pub/ml-archives/caml-list/2008/04/25992c9c9fa999fe1d35d961dd9917a2.en.html
+
+(11) Runtime endiannness expressions.  The suggested syntax is:
+
+    { field : len : endianness(expr) }
+
+    where expr would evaluate to something like `BigEndian or
+    `LittleEndian.
+
+    There are several protocols around where endianness is only
+    determined at runtime, examples are libpcap and TIFF.
+
+(12) More constant field lengths.
+
+(13) Implement native endian functions.
+
+(14) A proper test suite.
+
+(15) More examples:
+
+    ELF binaries
+    GIF images
index a8fd8ba..90f6acc 100644 (file)
@@ -29,7 +29,7 @@
    this module to both parse and generate binary formats, for
    example, communications protocols, disk formats and binary files.
 
    this module to both parse and generate binary formats, for
    example, communications protocols, disk formats and binary files.
 
-   {{:http://et.redhat.com/~rjones/bitmatch/}OCaml bitmatch website}
+   {{:http://code.google.com/p/bitmatch/}OCaml bitmatch website}
 
    {2 Examples}
 
 
    {2 Examples}
 
@@ -186,7 +186,7 @@ let make_message typ subtype param =
    match then the standard library [Match_failure] exception is
    thrown.
 
    match then the standard library [Match_failure] exception is
    thrown.
 
-   Patterns look a bit different from normal match patterns.  The
+   Patterns look a bit different from normal match patterns.  They
    consist of a list of bitfields separated by [;] where each bitfield
    contains a bind variable, the width (in bits) of the field, and
    other information.  Some example patterns:
    consist of a list of bitfields separated by [;] where each bitfield
    contains a bind variable, the width (in bits) of the field, and
    other information.  Some example patterns:
@@ -381,9 +381,8 @@ Bitmatch.hexdump_bitstring stdout bits ;;
    computed expression.
 
    Detection of compile-time constants is quite simplistic so only an
    computed expression.
 
    Detection of compile-time constants is quite simplistic so only an
-   immediate, simple integer is recognised as a constant and anything
-   else is considered a computed expression, even expressions such as
-   [5-2] which are obviously (to our eyes) constant.
+   simple integer literals and simple expressions (eg. [5*8]) are
+   recognized as constants.
 
    In any case the bit size of an integer is limited to the range
    \[1..64\].  This is detected as a compile-time error if that is
 
    In any case the bit size of an integer is limited to the range
    \[1..64\].  This is detected as a compile-time error if that is
index 83bb5d4..9d29340 100644 (file)
@@ -32,6 +32,42 @@ open Ast
  *)
 let debug = false
 
  *)
 let debug = false
 
+(* Work out if an expression is an integer constant.
+ *
+ * Returns [Some i] if so (where i is the integer value), else [None].
+ *
+ * Fairly simplistic algorithm: we can only detect simple constant
+ * expressions such as [k], [k+c], [k-c] etc.
+ *)
+let rec expr_is_constant = function
+  | <:expr< $int:i$ >> ->              (* Literal integer constant. *)
+    Some (int_of_string i)
+  | <:expr< $a$ + $b$ >> ->            (* Addition of constants. *)
+    (match expr_is_constant a, expr_is_constant b with
+     | Some a, Some b -> Some (a+b)
+     | _ -> None)
+  | <:expr< $a$ - $b$ >> ->            (* Subtraction. *)
+    (match expr_is_constant a, expr_is_constant b with
+     | Some a, Some b -> Some (a-b)
+     | _ -> None)
+  | <:expr< $a$ * $b$ >> ->            (* Multiplication. *)
+    (match expr_is_constant a, expr_is_constant b with
+     | Some a, Some b -> Some (a*b)
+     | _ -> None)
+  | <:expr< $a$ / $b$ >> ->            (* Division. *)
+    (match expr_is_constant a, expr_is_constant b with
+     | Some a, Some b -> Some (a/b)
+     | _ -> None)
+  | <:expr< $a$ lsl $b$ >> ->          (* Shift left. *)
+    (match expr_is_constant a, expr_is_constant b with
+     | Some a, Some b -> Some (a lsl b)
+     | _ -> None)
+  | <:expr< $a$ lsr $b$ >> ->          (* Shift right. *)
+    (match expr_is_constant a, expr_is_constant b with
+     | Some a, Some b -> Some (a lsr b)
+     | _ -> None)
+  | _ -> None                          (* Anything else is not constant. *)
+
 (* A field when used in a bitmatch (a pattern). *)
 type fpatt = {
   fpatt : patt;                                (* field matching pattern *)
 (* A field when used in a bitmatch (a pattern). *)
 type fpatt = {
   fpatt : patt;                                (* field matching pattern *)
@@ -189,9 +225,9 @@ and string_of_field_common { flen = flen;
                             endian = endian; signed = signed; t = t;
                             _loc = _loc } =
   let flen =
                             endian = endian; signed = signed; t = t;
                             _loc = _loc } =
   let flen =
-    match flen with
-    | <:expr< $int:i$ >> -> i
-    | _ -> "[non-const-len]" in
+    match expr_is_constant flen with
+    | Some i -> string_of_int i
+    | None -> "[non-const-len]" in
   let endian = string_of_endian endian in
   let signed = if signed then "signed" else "unsigned" in
   let t = string_of_t t in
   let endian = string_of_endian endian in
   let signed = if signed then "signed" else "unsigned" in
   let t = string_of_t t in
@@ -227,10 +263,7 @@ let output_constructor _loc fields =
       (* Is flen an integer constant?  If so, what is it?  This
        * is very simple-minded and only detects simple constants.
        *)
       (* Is flen an integer constant?  If so, what is it?  This
        * is very simple-minded and only detects simple constants.
        *)
-      let flen_is_const =
-       match flen with
-       | <:expr< $int:i$ >> -> Some (int_of_string i)
-       | _ -> None in
+      let flen_is_const = expr_is_constant flen in
 
       let name_of_int_construct_const = function
          (* XXX As an enhancement we should allow a 64-bit-only
 
       let name_of_int_construct_const = function
          (* XXX As an enhancement we should allow a 64-bit-only
@@ -489,10 +522,7 @@ let output_bitmatch _loc bs cases =
        (* Is flen an integer constant?  If so, what is it?  This
         * is very simple-minded and only detects simple constants.
         *)
        (* Is flen an integer constant?  If so, what is it?  This
         * is very simple-minded and only detects simple constants.
         *)
-       let flen_is_const =
-         match flen with
-         | <:expr< $int:i$ >> -> Some (int_of_string i)
-         | _ -> None in
+       let flen_is_const = expr_is_constant flen in
 
        let name_of_int_extract_const = function
            (* XXX As an enhancement we should allow a 64-bit-only
 
        let name_of_int_extract_const = function
            (* XXX As an enhancement we should allow a 64-bit-only