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