Skip to content

Commit 0f40525

Browse files
committed
Merge pull request #16 from dsheets/master
Trailing semicolons and pan-primitive buffers
2 parents f468707 + 6b44a98 commit 0f40525

File tree

2 files changed

+88
-66
lines changed

2 files changed

+88
-66
lines changed

CHANGES

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
0.8.0 (13-Oct-2013):
1+
0.8.1 (trunk):
2+
* Trailing semicolons are allowed in cstruct field definitions
3+
* Buffer elements can be any primitive integer, not just uint8
4+
5+
0.8.0 (2013-10-13):
26
* Improved ocamldoc for BE/LE modules.
37
* Add Travis-CI test scripts and fix `test.sh` script compilation.
48
* Support int32/int64 constant values in cenum like `VAL = 0xffffffffl`, useful for 32-bit hosts.
@@ -8,26 +12,24 @@
812
* Add `Cstruct.hexdump_to_buffer` to make spooling hexdump output easier.
913
* Generate `hexdump_foo` and `hexdump_foo_to_buffer` prettyprinting functions for a `cstruct foo`.
1014

11-
0.7.1 (06-Mar-2013):
15+
0.7.1 (2013-03-06):
1216
* Add `Async_cstruct.Pipe` to map pipes of `Cstruct` buffers to strings or `Bigsubstring`.
1317

14-
0.7.0 (25-Feb-2013):
15-
18+
0.7.0 (2013-02-25):
1619
* Add zero-copy conversion functions to/from the Core `Bigsubstring`.
1720
* Add an `of_string` function to simplify the construction from OCaml values.
1821
* Add Async interface to interoperate with Jane Street Core code.
1922

20-
0.6.2 (08-Feb-2013):
21-
23+
0.6.2 (2013-02-08):
2224
* Add experimental `cstruct.obuild` for the `obuild` build tool.
2325
* Use bounds checked version of all functions in the external interface.
2426
* Expose the `Cstruct.debug` to dump internal state of a buffer to a string.
2527
* Add `set_len` and `add_len` to manipulate the total-length field directly.
2628

27-
0.6.1 (20-Dec-2012):
29+
0.6.1 (2012-12-20):
2830
* Add `sendto`, `read` and `recvfrom` functions to the Lwt subpackage.
2931

30-
0.6.0 (20-Dec-2012):
32+
0.6.0 (2012-12-20):
3133
* Add fast bigarray<->string functions to replace byte-by-byte copies.
3234
* Add an Lwt sub-package to expose a write call.
3335
* Depend on ocplib-endian for fast low-level parsing of integers.
@@ -36,25 +38,25 @@
3638
on the minor heap rather than forcing a major heap allocation. It
3739
does alter the external API, so previous users of cstruct wont work.
3840

39-
0.5.3 (16-Dec-2012):
41+
0.5.3 (2012-12-16):
4042
* No functional changes, just OASIS packaging fix to right version.
4143

42-
0.5.2 (11-Dec-2012):
44+
0.5.2 (2012-12-11):
4345
* Remove the separate `xen` and `unix` subdirectories, as the
4446
portable `Bigarray` is now provided by the `xenbigarray` package.
4547

46-
0.5.1 (28-Sep-2012):
48+
0.5.1 (2012-09-28):
4749
* Add `string_to_<cenum>` function to match the `<cenum>_to_string`,
4850
primarily to help with command-line parsing of enum arguments.
4951

50-
0.5.0 (20-Sep-2012):
52+
0.5.0 (2012-09-20):
5153
* Add a signature generator for cstruct and cenum to permit their use in `.mli` files.
5254
* Use the more reliable revised syntax camlp4 quotation expander, to avoid
5355
broken AST output from antiquotations.
5456
* Switch the `xen/` version over to using OASIS also.
5557

56-
0.4.0 (02-Sep-2012):
58+
0.4.0 (2012-09-02):
5759
* Fix META file for use with Xen
5860

59-
0.3 (25-Aug-2012):
61+
0.3 (2012-08-25):
6062
* Initial public release

syntax/pa_cstruct.ml

Lines changed: 72 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ open Ast
2222

2323
type mode = Big_endian | Little_endian | Host_endian
2424

25+
type prim =
26+
| UInt8
27+
| UInt16
28+
| UInt32
29+
| UInt64
30+
2531
type ty =
26-
|UInt8
27-
|UInt16
28-
|UInt32
29-
|UInt64
30-
|Buffer of int
32+
| Prim of prim
33+
| Buffer of prim * int
3134

3235
type field = {
3336
field: string;
@@ -51,22 +54,24 @@ let ty_of_string =
5154
|_ -> None
5255

5356
let width_of_field f =
54-
match f.ty with
55-
|UInt8 -> 1
56-
|UInt16 -> 2
57-
|UInt32 -> 4
58-
|UInt64 -> 8
59-
|Buffer len -> len
57+
let rec width = function
58+
|Prim UInt8 -> 1
59+
|Prim UInt16 -> 2
60+
|Prim UInt32 -> 4
61+
|Prim UInt64 -> 8
62+
|Buffer (prim, len) -> (width (Prim prim)) * len
63+
in
64+
width f.ty
6065

6166
let field_to_string f =
62-
sprintf "%s %s"
63-
(match f.ty with
64-
|UInt8 -> "uint8_t"
65-
|UInt16 -> "uint16_t"
66-
|UInt32 -> "uint32_t"
67-
|UInt64 -> "uint64_t"
68-
|Buffer len -> sprintf "uint8_t[%d]" len
69-
) f.field
67+
let rec string = function
68+
|Prim UInt8 -> "uint8_t"
69+
|Prim UInt16 -> "uint16_t"
70+
|Prim UInt32 -> "uint32_t"
71+
|Prim UInt64 -> "uint64_t"
72+
|Buffer (prim, len) -> sprintf "%s[%d]" (string (Prim prim)) len
73+
in
74+
sprintf "%s %s" (string f.ty) f.field
7075

7176
let to_string t =
7277
sprintf "cstruct[%d] %s { %s }" t.len t.name
@@ -79,9 +84,8 @@ let parse_field _loc field field_type sz =
7984
|None -> loc_err _loc (sprintf "Unknown type %s" field_type)
8085
|Some ty -> begin
8186
let ty = match ty,sz with
82-
|_,None -> ty
83-
|UInt8,Some sz -> Buffer (int_of_string sz)
84-
|_,Some sz -> loc_err _loc "only uint8_t buffers supported"
87+
|_,None -> Prim ty
88+
|prim,Some sz -> Buffer (prim, int_of_string sz)
8589
in
8690
let off = -1 in
8791
{ field; ty; off }
@@ -118,69 +122,67 @@ let output_get _loc s f =
118122
let m = mode_mod _loc s.endian in
119123
let num x = <:expr< $int:string_of_int x$ >> in
120124
match f.ty with
121-
|Buffer len ->
125+
|Buffer (_, _) ->
126+
let len = width_of_field f in
122127
<:str_item<
123128
value $lid:op_name "get" s f$ src = Cstruct.sub src $num f.off$ $num len$ ;
124129
value $lid:op_name "copy" s f$ src = Cstruct.copy src $num f.off$ $num len$
125130
>>
126-
|ty ->
131+
|Prim prim ->
127132
<:str_item<
128133
value $lid:getter_name s f$ v =
129-
$match f.ty with
134+
$match prim with
130135
|UInt8 -> <:expr< Cstruct.get_uint8 v $num f.off$ >>
131136
|UInt16 -> <:expr< $m$.get_uint16 v $num f.off$ >>
132137
|UInt32 -> <:expr< $m$.get_uint32 v $num f.off$ >>
133138
|UInt64 -> <:expr< $m$.get_uint64 v $num f.off$ >>
134-
|Buffer len -> assert false
135139
$
136140
>>
137141

138-
let type_of_int_field _loc f =
139-
match f.ty with
142+
let type_of_int_field _loc = function
140143
|UInt8 -> <:ctyp<Cstruct.uint8>>
141144
|UInt16 -> <:ctyp<Cstruct.uint16>>
142145
|UInt32 -> <:ctyp<Cstruct.uint32>>
143146
|UInt64 -> <:ctyp<Cstruct.uint64>>
144-
|Buffer _ -> assert false
145147

146148
let output_get_sig _loc s f =
147149
match f.ty with
148-
|Buffer len ->
150+
|Buffer (_,_) ->
149151
<:sig_item<
150152
value $lid:op_name "get" s f$ : Cstruct.t -> Cstruct.t ;
151153
value $lid:op_name "copy" s f$ : Cstruct.t -> string >>
152-
|ty ->
153-
let retf = type_of_int_field _loc f in
154+
|Prim prim ->
155+
let retf = type_of_int_field _loc prim in
154156
<:sig_item< value $lid:getter_name s f$ : Cstruct.t -> $retf$ ; >>
155157

156158
let output_set _loc s f =
157159
let m = mode_mod _loc s.endian in
158160
let num x = <:expr< $int:string_of_int x$ >> in
159161
match f.ty with
160-
|Buffer len ->
162+
|Buffer (_,_) ->
163+
let len = width_of_field f in
161164
<:str_item<
162165
value $lid:setter_name s f$ src srcoff dst = Cstruct.blit_from_string src srcoff dst $num f.off$ $num len$ ;
163166
value $lid:op_name "blit" s f$ src srcoff dst = Cstruct.blit src srcoff dst $num f.off$ $num len$
164167
>>
165-
|ty ->
168+
|Prim prim ->
166169
<:str_item<
167-
value $lid:setter_name s f$ v x = $match f.ty with
170+
value $lid:setter_name s f$ v x = $match prim with
168171
|UInt8 -> <:expr< Cstruct.set_uint8 v $num f.off$ x >>
169172
|UInt16 -> <:expr< $m$.set_uint16 v $num f.off$ x >>
170173
|UInt32 -> <:expr< $m$.set_uint32 v $num f.off$ x >>
171174
|UInt64 -> <:expr< $m$.set_uint64 v $num f.off$ x >>
172-
|Buffer len -> assert false
173175
$
174176
>>
175177

176178
let output_set_sig _loc s f =
177179
match f.ty with
178-
|Buffer len ->
180+
|Buffer (_,_) ->
179181
<:sig_item<
180182
value $lid:setter_name s f$ : string -> int -> Cstruct.t -> unit ;
181183
value $lid:op_name "blit" s f$ : Cstruct.t -> int -> Cstruct.t -> unit >>
182-
|ty ->
183-
let retf = type_of_int_field _loc f in
184+
|Prim prim ->
185+
let retf = type_of_int_field _loc prim in
184186
<:sig_item< value $lid:setter_name s f$ : Cstruct.t -> $retf$ -> unit >>
185187

186188
let output_sizeof _loc s =
@@ -199,10 +201,16 @@ let output_hexdump _loc s =
199201
<:expr<
200202
$a$; Buffer.add_string _buf $str:" "^f.field^" = "$;
201203
$match f.ty with
202-
|UInt8 |UInt16 -> <:expr< Printf.bprintf _buf "0x%x\n" ($lid:getter_name s f$ v) >>
203-
|UInt32 -> <:expr< Printf.bprintf _buf "0x%lx\n" ($lid:getter_name s f$ v) >>
204-
|UInt64 -> <:expr< Printf.bprintf _buf "0x%Lx\n" ($lid:getter_name s f$ v) >>
205-
|Buffer len -> <:expr< Printf.bprintf _buf "<buffer length %d>" $int:string_of_int len$; Cstruct.hexdump_to_buffer _buf ($lid:getter_name s f$ v) >>
204+
|Prim (UInt8|UInt16) ->
205+
<:expr< Printf.bprintf _buf "0x%x\n" ($lid:getter_name s f$ v) >>
206+
|Prim UInt32 ->
207+
<:expr< Printf.bprintf _buf "0x%lx\n" ($lid:getter_name s f$ v) >>
208+
|Prim UInt64 ->
209+
<:expr< Printf.bprintf _buf "0x%Lx\n" ($lid:getter_name s f$ v) >>
210+
|Buffer (_,_) ->
211+
<:expr< Printf.bprintf _buf "<buffer %s>"
212+
$str: field_to_string f$;
213+
Cstruct.hexdump_to_buffer _buf ($lid:getter_name s f$ v) >>
206214
$ >>
207215
) <:expr< >> s.fields
208216
in
@@ -248,7 +256,7 @@ let output_struct_sig _loc s =
248256
let output_enum _loc name fields width =
249257
let intfn,pattfn = match ty_of_string width with
250258
|None -> loc_err _loc ("enum: unknown width specifier " ^ width)
251-
|Some UInt8 |Some UInt16 ->
259+
|Some (UInt8 | UInt16) ->
252260
(fun i -> <:expr< $int:Int64.to_string i$ >>),
253261
(fun i -> <:patt< $int:Int64.to_string i$ >>)
254262
|Some UInt32 ->
@@ -257,7 +265,6 @@ let output_enum _loc name fields width =
257265
|Some UInt64 ->
258266
(fun i -> <:expr< $int64:Printf.sprintf "0x%Lx" i$ >>),
259267
(fun i -> <:patt< $int64:Printf.sprintf "0x%Lx" i$ >>)
260-
|Some (Buffer _) -> loc_err _loc "enum: array types not allowed"
261268
in
262269
let decls = tyOr_of_list (List.map (fun (f,_) ->
263270
<:ctyp< $uid:f$ >>) fields) in
@@ -286,10 +293,9 @@ let output_enum _loc name fields width =
286293
let output_enum_sig _loc name fields width =
287294
let oty = match ty_of_string width with
288295
|None -> loc_err _loc ("enum: unknown width specifier " ^ width)
289-
|Some UInt8|Some UInt16 -> <:ctyp<int>>
296+
|Some (UInt8|UInt16) -> <:ctyp<int>>
290297
|Some UInt32 -> <:ctyp<int32>>
291298
|Some UInt64 -> <:ctyp<int64>>
292-
|Some (Buffer _) -> loc_err _loc "enum: array types not allowed"
293299
in
294300
let decls = tyOr_of_list (List.map (fun (f,_) ->
295301
<:ctyp< $uid:f$ >>) fields) in
@@ -316,10 +322,14 @@ EXTEND Gram
316322
]
317323
];
318324

325+
constr_field_decl: [
326+
[ field = constr_field -> [field]
327+
| field = constr_field; ";"; rest = constr_field_decl -> field::rest
328+
| field = constr_field; ";" -> [field] ]
329+
];
330+
319331
constr_fields: [
320-
[ "{"; fields = LIST0 constr_field SEP ";"; "}" ->
321-
fields
322-
]
332+
[ "{"; fields = constr_field_decl; "}" -> fields ]
323333
];
324334

325335
constr_enum: [
@@ -330,12 +340,22 @@ EXTEND Gram
330340
| f = UIDENT; "="; i = INT -> (f, Some (Int64.of_string i)) ]
331341
];
332342

343+
constr_enum_decl: [
344+
[ enum = constr_enum -> [enum]
345+
| enum = constr_enum; ";"; rest = constr_enum_decl -> enum::rest
346+
| enum = constr_enum; ";" -> [enum] ]
347+
];
348+
349+
constr_enums: [
350+
[ "{"; enums = constr_enum_decl; "}" -> enums ]
351+
];
352+
333353
sig_item: [
334354
[ "cstruct"; name = LIDENT; fields = constr_fields;
335355
"as"; endian = LIDENT ->
336356
output_struct_sig _loc (create_struct _loc endian name fields)
337357
] |
338-
[ "cenum"; name = LIDENT; "{"; fields = LIST0 [ constr_enum ] SEP ";"; "}";
358+
[ "cenum"; name = LIDENT; fields = constr_enums;
339359
"as"; width = LIDENT ->
340360
let n = ref Int64.minus_one in
341361
let incr_n () = n := Int64.succ !n in
@@ -353,7 +373,7 @@ EXTEND Gram
353373
"as"; endian = LIDENT ->
354374
output_struct _loc (create_struct _loc endian name fields)
355375
] |
356-
[ "cenum"; name = LIDENT; "{"; fields = LIST0 [ constr_enum ] SEP ";"; "}";
376+
[ "cenum"; name = LIDENT; fields = constr_enums;
357377
"as"; width = LIDENT ->
358378
let n = ref Int64.minus_one in
359379
let incr_n () = n := Int64.succ !n in

0 commit comments

Comments
 (0)