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")