let rec convert_declarator_iter ~env ty ?argnames declbody
    : declaration_specifier list * declarator = 
  match ty.ct_ty with
    Tpointer(t1) ->
      convert_declarator_iter ~env t1 (PdeclPointer(get_type_qualifiers ty,declbody))
  | Tarray(t1,sz_opt) ->
      convert_declarator_iter ~env t1 (PdeclArray(declbody, Option.map (constant_exp_of_big_int ~loc:dummy_loc) sz_opt))
  | Tstruct(id) ->
      let quals = get_type_qualifiers_speclist ty in
      let name = find_struct_name ~env id in
      let is_union = is_union ~env id in
      let tspec = [TypeSpec (PtypespecStruct(is_union,Some name,None))] in
      (quals @ tspec), declbody
  | Tfunction(args,varargs,rettype) ->
      let argtree = 
        match argnames with
          None ->
            List.map
              (fun t -> 
                let ds, dc = convert_declarator_anonymous ~env t in
                PpdeclAbstract(ds,dc))
              args
        | Some argnames ->
            List.map2
              (fun t n -> 
                let ds, dc = convert_declarator ~env t n in
                PpdeclAbstract(ds,dc))
              args argnames
      in
      let argtree = 
        if varargs then
          if argtree = [] then
            [] (* K&R style empty decl *)
          else 
            argtree @ [PpdeclVariant]
        else
          if argtree = [] then
            [PpdeclAbstract(void_spectreelist, PdeclAnonymous)]
          else
            argtree
      in
      convert_declarator_iter ~env rettype (PdeclFuncType(declbody, argtree))
  | Tbuiltin(t) ->
      let quals = get_type_qualifiers_speclist ty in
      let tspec = builtin_to_typespec t in
      (quals @ tspec), declbody
  | Tvoid ->
      let quals = get_type_qualifiers_speclist ty in
      quals @ void_spectreelist, declbody

and convert_declarator ~env ty ?argnames ident = 
  convert_declarator_iter ~env ty ?argnames (PdeclIdent ident)

and convert_declarator_anonymous ~env ty = 
  convert_declarator_iter ~env ty (PdeclAnonymous)