Added computed offset field
[ocaml-bitstring.git] / bitmatch_persistent.mli
1 (** Bitmatch persistent patterns. *)
2 (* Copyright (C) 2008 Red Hat Inc., Richard W.M. Jones
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  * $Id$
19  *)
20
21 (**
22    {b Warning:} This documentation is for ADVANCED USERS ONLY.
23    If you are not an advanced user, you are probably looking
24    for {{:Bitmatch.html}the Bitmatch documentation}.
25
26    {{:#reference}Jump straight to the reference section for
27    documentation on types and functions}.
28
29    {2 Introduction}
30
31    Bitmatch allows you to name sets of fields and reuse them
32    elsewhere.  For example if you frequently need to parse
33    Pascal-style strings in the form length byte + string, then you
34    could name the [{ strlen : 8 : int; str : strlen*8 : string }]
35    pattern and reuse it everywhere by name.
36
37    These are called {b persistent patterns}.
38
39    The basic usage is:
40
41 {v
42 (* Create a persistent pattern called 'pascal_string' which
43  * matches Pascal-style strings (length byte + string).
44  *)
45 let bitmatch pascal_string =
46   \{ strlen : 8 : int;
47     str : strlen*8 : string }
48
49 let is_pascal_string bits =
50   bitmatch bits with
51   | \{ :pascal_string } ->
52     printf "matches a Pascal string %s, len %d bytes\n"
53       str strlen
54 v}
55
56    or:
57
58 {v
59 (* Load a persistent pattern from a file. *)
60 open bitmatch "pascal.bmpp"
61
62 let is_pascal_string bits =
63   bitmatch bits with
64   | \{ :pascal_string } ->
65     printf "matches a Pascal string %s, len %d bytes\n"
66       str strlen
67 v}
68
69    {3 Important notes}
70
71    There are some important things you should know about
72    persistent patterns before you decide to use them:
73
74    'Persistent' refers to the fact that they can be saved into binary
75    files.  However these binary files use OCaml [Marshal] module and
76    depend (sometimes) on the version of OCaml used to generate them
77    and (sometimes) the version of bitmatch used.  So your build system
78    should rebuild these files from source when your code is rebuilt.
79
80    Persistent patterns are syntactic.  They work in the same way
81    as cutting and pasting (or [#include]-ing) code.  For example
82    if a persistent pattern binds a field named [len], then any
83    uses of [len] following in the surrounding pattern could
84    be affected.
85
86    Programs which generate and manipulate persistent patterns have to
87    link to camlp4.  Since camlp4 in OCaml >= 3.10 is rather large, we
88    have placed this code into this separate submodule, so that
89    programs which just use bitmatch don't need to pull in the whole of
90    camlp4.  This restriction does not apply to code which only uses
91    persistent patterns but does not generate them.  If the distinction
92    isn't clear, use [ocamlobjinfo] to look at the dependencies of your
93    [*.cmo] files.
94
95    Persistent patterns can be generated in several ways, but they
96    can only be {i used} by the [pa_bitmatch] syntax extension.
97    This means they are purely compile-time constructs.  You
98    cannot use them to make arbitrary patterns and run those
99    patterns (not unless your program runs [ocamlc] to make a [*.cmo]
100    file then dynamically links to the [*.cmo] file).
101
102    {2 Named patterns}
103
104    A named pattern is a way to name a pattern and use it later
105    in the same source file.  To name a pattern, use:
106
107    [let bitmatch name = { fields ... } ;;]
108
109    and you can then use the name later on inside another pattern,
110    by prefixing the name with a colon.
111    For example:
112
113    [bitmatch bits with { :name } -> ...]
114
115    You can nest named patterns within named patterns to any depth.
116
117    Currently the use of named patterns is somewhat limited.
118    The restrictions are:
119
120    Named patterns can only be used within the same source file, and
121    the names occupy a completely separate namespace from anything
122    else in the source file.
123
124    The [let bitmatch] syntax only works at the top level.  We may
125    add a [let bitmatch ... in] for inner levels later.
126
127    Because you cannot rename the bound identifiers in named
128    patterns, you can effectively only use them once in a
129    pattern.  For example, [{ :name; :name }] is legal, but
130    any bindings in the first name would be overridden by
131    the second name.
132
133    There are no "named constructors" yet, but the machinery
134    is in place to do this, and we may add them later.
135
136    {2 Persistent patterns in files}
137
138    More useful than just naming patterns, you can load
139    persistent patterns from external files.  The patterns
140    in these external files can come from a variety of sources:
141    for example, in the [cil-tools] subdirectory are some
142    {{:http://cil.sf.net/}Cil-based} tools for importing C
143    structures from header files.  You can also generate
144    your own files or write your own tools, as described below.
145
146    To use the persistent pattern(s) from a file do:
147
148    [open bitmatch "filename.bmpp" ;;]
149
150    A list of zero or more {!named} patterns are read from the file
151    and each is bound to a name (as contained in the file),
152    and then the patterns can be used with the usual [:name]
153    syntax described above.
154
155    {3 Extension}
156
157    The standard extension is [.bmpp].  This is just a convention
158    and you can use any extension you want.
159
160    {3 Directory search order}
161
162    If the filename is an absolute or explicit path, then we try to
163    load it from that path and stop if it fails.  See the [Filename]
164    module in the standard OCaml library for the definitions of
165    "absolute path" and "explicit path".  Otherwise we use the
166    following directory search order:
167
168    - Relative to the current directory
169    - Relative to the OCaml library directory
170
171    {3 bitmatch-objinfo}
172
173    The [bitmatch-objinfo] command can be run on a file in order
174    to print out the patterns in the file.
175
176    {3 Constructors}
177
178    We haven't implemented persistent constructors yet, although
179    the machinery is in place to make this happen.  Any constructors
180    found in the file are ignored.
181
182    {2 Creating your own persistent patterns}
183
184    If you want to write a tool to import bitstrings from an
185    exotic location or markup language, you will need
186    to use the functions found in the {{:#reference}reference section}.
187
188    I will describe using an example here of how you would
189    programmatically create a persistent pattern which
190    matches Pascal-style "length byte + data" strings.
191    Firstly note that there are two fields, so our pattern
192    will be a list of length 2 and type {!pattern}.
193
194    You will need to create a camlp4 location object ([Loc.t])
195    describing the source file.  This source file is used
196    to generate useful error messages for the user, so
197    you may want to set it to be the name and location in
198    the file that your tool reads for input.  By convention,
199    locations are bound to name [_loc]:
200
201    {v
202    let _loc = Loc.move_line 42 (Loc.mk "input.xml")
203    v}
204
205    Create a pattern field representing a length field which is 8 bits wide,
206    bound to the identifier [len]:
207
208    {v
209    let len_field = create_pattern_field _loc
210    let len_field = set_length_int len_field 8
211    let len_field = set_lident_patt len_field "len"
212    v}
213
214    Create a pattern field representing a string of [len*8] bits.
215    Note that the use of [<:expr< >>] quotation requires
216    you to preprocess your source with [camlp4of]
217    (see {{:http://brion.inria.fr/gallium/index.php/Reflective_OCaml}this
218    page on Reflective OCaml}).
219
220    {v
221    let str_field = create_pattern_field _loc
222    let str_field = set_length str_field <:expr< len*8 >>
223    let str_field = set_lident_patt str_field "str"
224    let str_field = set_type_string str_field
225    v}
226
227    Join the two fields together and name it:
228
229    {v
230    let pattern = [len_field; str_field]
231    let named_pattern = "pascal_string", Pattern pattern
232    v}
233
234    Save it to a file:
235
236    {v
237    let chan = open_out "output.bmpp" in
238    named_to_channel chan named_pattern;
239    close_out chan
240    v}
241
242    You can now use this pattern in another program like this:
243
244    {v
245    open bitmatch "output.bmpp" ;;
246    let parse_pascal_string bits =
247    bitmatch bits with
248    | \{ :pascal_string } -> str, len
249    | \{ _ } -> invalid_arg "not a Pascal string"
250    v}
251
252    You can write more than one named pattern to the output file, and
253    they will all be loaded at the same time by [open bitmatch ".."]
254    (obviously you should give each pattern a different name).  To do
255    this, just call {!named_to_channel} as many times as needed.
256
257    {2:reference Reference}
258
259    {3 Types}
260 *)
261
262 type patt = Camlp4.PreCast.Syntax.Ast.patt
263 type expr = Camlp4.PreCast.Syntax.Ast.expr
264 type loc_t = Camlp4.PreCast.Syntax.Ast.Loc.t
265 (** Just short names for the camlp4 types. *)
266
267 type 'a field
268 (** A field in a persistent pattern or persistent constructor. *)
269
270 type pattern = patt field list
271 (** A persistent pattern (used in [bitmatch] operator), is just a
272     list of pattern fields. *)
273
274 type constructor = expr field list
275 (** A persistent constructor (used in [BITSTRING] operator), is just a
276     list of constructor fields. *)
277
278 type named = string * alt
279 and alt =
280   | Pattern of pattern                  (** Pattern *)
281   | Constructor of constructor          (** Constructor *)
282 (** A named pattern or constructor.
283
284     The name is used when binding a pattern from a file, but
285     is otherwise ignored. *)
286
287 (** {3 Printers} *)
288
289 val string_of_pattern : pattern -> string
290 val string_of_constructor : constructor -> string
291 val string_of_field : 'a field -> string
292 (** Convert patterns, constructors or individual fields
293     into printable strings for debugging purposes.
294
295     The strings look similar to the syntax used by bitmatch, but
296     some things cannot be printed fully, eg. length expressions. *)
297
298 (** {3 Persistence} *)
299
300 val named_to_channel : out_channel -> named -> unit
301 (** Save a pattern/constructor to an output channel. *)
302
303 val named_to_string : named -> string
304 (** Serialize a pattern/constructor to a string. *)
305
306 val named_to_buffer : string -> int -> int -> named -> int
307 (** Serialize a pattern/constructor to part of a string, return the length. *)
308
309 val named_from_channel : in_channel -> named
310 (** Load a pattern/constructor from an output channel.
311
312     Note: This is not type safe.  The pattern/constructor must
313     have been written out under the same version of OCaml and
314     the same version of bitmatch. *)
315
316 val named_from_string : string -> int -> named
317 (** Load a pattern/constructor from a string at offset within the string.
318
319     Note: This is not type safe.  The pattern/constructor must
320     have been written out under the same version of OCaml and
321     the same version of bitmatch. *)
322
323 (** {3 Create pattern fields}
324
325     These fields are used in pattern matches ([bitmatch]). *)
326
327 val create_pattern_field : loc_t -> patt field
328 (** Create a pattern field.
329
330     The pattern is unbound, the type is set to [int], bit length to [32],
331     endianness to [BigEndian], signedness to unsigned ([false]),
332     source code location to the [_loc] parameter, and no offset expression.
333
334     To create a complete field you need to call the [set_*]
335     functions.  For example, to create [{ len : 8 : int }]
336     you would do:
337
338 {v
339     let field = create_pattern_field _loc in
340     let field = set_lident_patt field "len" in
341     let field = set_length_int field 8 in
342 v}
343 *)
344
345 val set_lident_patt : patt field -> string -> patt field
346 (** Sets the pattern to the pattern binding an identifier
347     given in the string.
348
349     The effect is that the field [{ len : 8 : int }] could
350     be created by calling [set_lident_patt field "len"]. *)
351
352 val set_int_patt : patt field -> int -> patt field
353 (** Sets the pattern field to the pattern which matches an integer.
354
355     The effect is that the field [{ 2 : 8 : int }] could
356     be created by calling [set_int_patt field 2]. *)
357
358 val set_string_patt : patt field -> string -> patt field
359 (** Sets the pattern field to the pattern which matches a string.
360
361     The effect is that the field [{ "MAGIC" : 8*5 : string }] could
362     be created by calling [set_int_patt field "MAGIC"]. *)
363
364 val set_unbound_patt : patt field -> patt field
365 (** Sets the pattern field to the unbound pattern (usually written [_]).
366
367     The effect is that the field [{ _ : 8 : int }] could
368     be created by calling [set_unbound_patt field]. *)
369
370 val set_patt : patt field -> patt -> patt field
371 (** Sets the pattern field to an arbitrary OCaml pattern match. *)
372
373 val set_length_int : 'a field -> int -> 'a field
374 (** Sets the length in bits of a field to a constant integer.
375
376     The effect is that the field [{ len : 8 : string }] could
377     be created by calling [set_length field 8]. *)
378
379 val set_length : 'a field -> expr -> 'a field
380 (** Sets the length in bits of a field to an OCaml expression.
381
382     The effect is that the field [{ len : 2*i : string }] could
383     be created by calling [set_length field <:expr< 2*i >>]. *)
384
385 val set_endian : 'a field -> Bitmatch.endian -> 'a field
386 (** Sets the endianness of a field to the constant endianness.
387
388     The effect is that the field [{ _ : 16 : bigendian }] could
389     be created by calling [set_endian field Bitmatch.BigEndian]. *)
390
391 val set_endian_expr : 'a field -> expr -> 'a field
392 (** Sets the endianness of a field to an endianness expression.
393
394     The effect is that the field [{ _ : 16 : endian(e) }] could
395     be created by calling [set_endian_expr field e]. *)
396
397 val set_signed : 'a field -> bool -> 'a field
398 (** Sets the signedness of a field to a constant signedness.
399
400     The effect is that the field [{ _ : 16 : signed }] could
401     be created by calling [set_signed field true]. *)
402
403 val set_type_int : 'a field -> 'a field
404 (** Sets the type of a field to [int].
405
406     The effect is that the field [{ _ : 16 : int }] could
407     be created by calling [set_type_int field]. *)
408
409 val set_type_string : 'a field -> 'a field
410 (** Sets the type of a field to [string].
411
412     The effect is that the field [{ str : 16 : string }] could
413     be created by calling [set_type_string field]. *)
414
415 val set_type_bitstring : 'a field -> 'a field
416 (** Sets the type of a field to [bitstring].
417
418     The effect is that the field [{ _ : 768 : bitstring }] could
419     be created by calling [set_type_bitstring field]. *)
420
421 val set_location : 'a field -> loc_t -> 'a field
422 (** Sets the source code location of a field.  This is used when
423     pa_bitmatch displays error messages. *)
424
425 val set_offset_int : 'a field -> int -> 'a field
426 (** Set the offset expression for a field to the given number.
427
428     The effect is that the field [{ _ : 8 : offset(160) }] could
429     be created by calling [set_offset_int field 160]. *)
430
431 val set_offset : 'a field -> expr -> 'a field
432 (** Set the offset expression for a field to the given expression.
433
434     The effect is that the field [{ _ : 8 : offset(160) }] could
435     be created by calling [set_offset_int field <:expr< 160 >>]. *)
436
437 val set_no_offset : 'a field -> 'a field
438 (** Remove the offset expression from a field.  The field will
439     follow the previous field, or if it is the first field will
440     be at offset zero. *)
441
442 (** {3 Create constructor fields}
443
444     These fields are used in constructors ([BITSTRING]). *)
445
446 val create_constructor_field : loc_t -> expr field
447 (** Create a constructor field.
448
449     The defaults are the same as for {!create_pattern_field}
450     except that the expression is initialized to [0].
451 *)
452
453 val set_lident_expr : expr field -> string -> expr field
454 (** Sets the expression in a constructor field to an expression
455     which uses the identifier.
456
457     The effect is that the field [{ len : 8 : int }] could
458     be created by calling [set_lident_expr field "len"]. *)
459
460 val set_int_expr : expr field -> int -> expr field
461 (** Sets the expression to the value of the integer.
462
463     The effect is that the field [{ 2 : 8 : int }] could
464     be created by calling [set_int_expr field 2]. *)
465
466 val set_string_expr : expr field -> string -> expr field
467 (** Sets the expression to the value of the string.
468
469     The effect is that the field [{ "MAGIC" : 8*5 : string }] could
470     be created by calling [set_int_expr field "MAGIC"]. *)
471
472 val set_expr : expr field -> expr -> expr field
473 (** Sets the expression field to an arbitrary OCaml expression. *)
474
475 (** {3 Accessors} *)
476
477 val get_patt : patt field -> patt
478 (** Get the pattern from a pattern field. *)
479
480 val get_expr : expr field -> expr
481 (** Get the expression from an expression field. *)
482
483 val get_length : 'a field -> expr
484 (** Get the length in bits from a field.  Note that what is returned
485     is an OCaml expression, since lengths can be non-constant. *)
486
487 type endian_expr =
488   | ConstantEndian of Bitmatch.endian
489   | EndianExpr of expr
490
491 val get_endian : 'a field -> endian_expr
492 (** Get the endianness of a field.  This is an {!endian_expr} which
493     could be a constant or an OCaml expression. *)
494
495 val get_signed : 'a field -> bool
496 (** Get the signedness of a field. *)
497
498 type field_type = Int | String | Bitstring
499
500 val get_type : 'a field -> field_type
501 (** Get the type of a field, [Int], [String] or [Bitstring]. *)
502
503 val get_location : 'a field -> loc_t
504 (** Get the source code location of a field. *)
505
506 val get_offset : 'a field -> expr option
507 (** Get the offset expression of a field, or [None] if there is none. *)