let rec parse_list_initializations ~env stream et size =
match size with
None ->
let rec iter () =
if isempty_stream stream then []
else
let _, i = parse_initialization ~type_change_allowed:false ~env stream et in
i :: iter ()
in
(iter ())
| Some sz ->
let sz = int_of_big_int sz in
let rec iter n =
if n >= sz then []
else
let _, i = parse_initialization ~type_change_allowed:false ~env stream et in
i :: iter (n + 1)
in
(iter 0)
and parse_struct_initializations ~env stream struct_id =
let desc = get_struct_desc ~env struct_id in
let rec iter_bfields = function
[] -> []
| (_,t,_,_)::tl ->
let _, i = parse_initialization ~type_change_allowed:false ~env stream t in
i :: iter_bfields tl
in
let rec iter = function
[] -> []
| (_, NormalField { sf_type = t }) :: tl ->
let _, i = parse_initialization ~type_change_allowed:false ~env stream t in
i :: (iter tl)
| (_, BitField { s_bf_fields = bfl }) :: tl ->
let l = iter_bfields bfl in
l @ (iter tl)
in
CTTinitList (iter desc.str_fields)
and parse_initialization ?(type_change_allowed = true) ~env (stream : initstream) typ =
match typ.ct_ty with
Tvoid -> raise (Type_Error_local("initializing void value?"))
| Tbuiltin(_) | Tpointer(_) -> begin
match pop_stream stream with
Ilist _ -> raise (Type_Error_local("initializing scalar with list"))
| Isingle e | Istring (e,_) ->
let e = assign_coerce ~check_qual:qual_dcare e typ in
typ, CTTinitExp e
end
| Tarray({ct_ty = Tbuiltin((Tchar | Tuchar | Tschar))} as et,sz)
when is_next_string_stream stream -> begin
match pop_stream stream with
Istring(e,s) ->
let init_sz = String.length s + 1 in
let new_typ, e =
match sz with
None ->
if type_change_allowed then
{ typ with ct_ty = Tarray(et, Some (big_int_of_int init_sz)) }, CTTinitExp e
else
raise (Type_Error_local "array of unspecified size not allowed here")
| Some sz ->
if lt_big_int (big_int_of_int init_sz) sz then
typ, CTTinitExp e
else if eq_big_int (big_int_of_int (init_sz - 1)) sz then
typ, CTTinitExp e
else
raise (TypeError_typed(e, "array size mismatch"))
in
new_typ, e
| _ -> assert false
end
| Tarray(et,sz) -> begin
match peek_stream stream with
Ilist inside_stream -> begin
ignore (pop_stream stream);
let inits = parse_list_initializations ~env inside_stream et sz in
match sz with
None ->
if type_change_allowed then
let init_sz = List.length inits in
{ typ with ct_ty = Tarray(et, Some (big_int_of_int init_sz)) }, CTTinitList inits
else
raise (Type_Error_local "array of unspecified size not allowed here")
| Some _ ->
if not (isempty_stream inside_stream) then
raise (Type_Error_local "too many initializers")
else
typ, CTTinitList inits
end
| Isingle e | Istring(e,_) -> begin
match sz with
None ->
raise (Type_Error_local "array of unspecified size not allowed here")
|
Some _ ->
let inits = parse_list_initializations ~env stream et sz in
typ, CTTinitList inits
end
end
| Tstruct(id) -> begin
match peek_stream stream with
Ilist inside_stream -> begin
ignore (pop_stream stream);
let inits = parse_struct_initializations ~env inside_stream id in
if not (isempty_stream inside_stream) then
raise (Type_Error_local "too many initializers")
else
typ, inits
end
| Isingle e | Istring(e,_) -> begin
let inits = parse_struct_initializations ~env stream id in
typ, inits
end
end
| Tfunction(_) ->
raise (Type_Error_local "initializing function")