123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243(****************************************************************************)(* *)(* This file is part of MOPSA, a Modular Open Platform for Static Analysis. *)(* *)(* Copyright (C) 2019 The MOPSA Project. *)(* *)(* This program is free software: you can redistribute it and/or modify *)(* it under the terms of the GNU Lesser General Public License as published *)(* by the Free Software Foundation, either version 3 of the License, or *)(* (at your option) any later version. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* You should have received a copy of the GNU Lesser General Public License *)(* along with this program. If not, see <http://www.gnu.org/licenses/>. *)(* *)(****************************************************************************)openFormatopenMopsaopenAstletprint_implicit_cast=falseletrecpp_c_type_shortfmt=function|T_c_void->pp_print_stringfmt"void"|T_c_bool->pp_print_stringfmt"b"|T_c_integer(C_signed_char)->pp_print_stringfmt"s8"|T_c_integer(C_unsigned_char)->pp_print_stringfmt"u8"|T_c_integer(C_signed_short)->pp_print_stringfmt"s16"|T_c_integer(C_unsigned_short)->pp_print_stringfmt"u16"|T_c_integer(C_signed_int)->pp_print_stringfmt"s32"|T_c_integer(C_unsigned_int)->pp_print_stringfmt"u32"|T_c_integer(C_signed_long)->pp_print_stringfmt"sl"|T_c_integer(C_unsigned_long)->pp_print_stringfmt"ul"|T_c_integer(C_signed_long_long)->pp_print_stringfmt"sll"|T_c_integer(C_unsigned_long_long)->pp_print_stringfmt"ull"|T_c_integer(C_signed_int128)->pp_print_stringfmt"s128"|T_c_integer(C_unsigned_int128)->pp_print_stringfmt"u128"|T_c_float(C_float)->pp_print_stringfmt"f"|T_c_float(C_double)->pp_print_stringfmt"d"|T_c_float(C_long_double)->pp_print_stringfmt"ld"|T_c_float(C_float128)->pp_print_stringfmt"q"|T_c_pointer(t)->fprintffmt"%a*"pp_c_type_shortt|T_c_array(t,C_array_no_length)->fprintffmt"%a[]"pp_c_type_shortt|T_c_array(t,C_array_length_cstn)->fprintffmt"%a[%s]"pp_c_type_shortt(Z.to_stringn)|T_c_array(t,C_array_length_expre)->fprintffmt"%a[%a]"pp_c_type_shorttpp_expre|T_c_functionNone->()|T_c_function(Somef)->fprintffmt"(%a)"pp_c_type_shortf.c_ftype_return|T_c_typedef(typedef)->pp_c_type_shortfmttypedef.c_typedef_def|T_c_record({c_record_kind=C_struct}asrecord)->fprintffmt"s %s"record.c_record_org_name|T_c_record({c_record_kind=C_union}asrecord)->fprintffmt"u %s"record.c_record_org_name|T_c_bitfield(t,s)->fprintffmt"bf(%a:%d)"pp_c_type_shortts|T_c_qualified(qual,t)->letl=(ifqual.c_qual_is_constthen["c"]else[])@(ifqual.c_qual_is_volatilethen["v"]else[])@(ifqual.c_qual_is_restrictthen["r"]else[])inletqual=String.concat" "linfprintffmt"%s %a"qualpp_c_type_shortt|T_c_enum(enum)->fprintffmt"e %s"enum.c_enum_org_name|t->panic"pp_c_type_short: unsupported type %a"pp_typtletrecpp_c_initfmt=function|C_init_expr(e)->pp_exprfmte|C_init_list([],Somefiller)->fprintffmt"{%a ...}"pp_c_initfiller|C_init_list(l,filler)->fprintffmt"{%a, filler=%a}"(pp_print_list~pp_sep:(funfmt()->fprintffmt", ")pp_c_init)l(OptionExt.printpp_c_init)filler|C_init_implicitt->assertfalseletpp_character_kindfmt=function|C_char_ascii->()|C_char_wide->pp_print_stringfmt"L"|C_char_utf8->pp_print_stringfmt"u8"|C_char_utf16->pp_print_stringfmt"u"|C_char_utf32->pp_print_stringfmt"U"|C_char_unevaluated->()let()=register_typ_pp(fundefaultfmttyp->matchtypwith|T_c_void->pp_print_stringfmt"void"|T_c_bool->pp_print_stringfmt"bool"|T_c_integer(C_signed_char)->pp_print_stringfmt"signed char"|T_c_integer(C_unsigned_char)->pp_print_stringfmt"unsigned char"|T_c_integer(C_signed_short)->pp_print_stringfmt"signed short"|T_c_integer(C_unsigned_short)->pp_print_stringfmt"unsigned short"|T_c_integer(C_signed_int)->pp_print_stringfmt"signed int"|T_c_integer(C_unsigned_int)->pp_print_stringfmt"unsigned int"|T_c_integer(C_signed_long)->pp_print_stringfmt"signed long"|T_c_integer(C_unsigned_long)->pp_print_stringfmt"unsigned long"|T_c_integer(C_signed_long_long)->pp_print_stringfmt"signed long long"|T_c_integer(C_unsigned_long_long)->pp_print_stringfmt"unsigned long long"|T_c_integer(C_signed_int128)->pp_print_stringfmt"signed int128"|T_c_integer(C_unsigned_int128)->pp_print_stringfmt"unsigned int128"|T_c_float(C_float)->pp_print_stringfmt"float"|T_c_float(C_double)->pp_print_stringfmt"double"|T_c_float(C_long_double)->pp_print_stringfmt"long double"|T_c_float(C_float128)->pp_print_stringfmt"__float128"|T_c_pointer(t)->fprintffmt"%a *"pp_typt|T_c_array(t,C_array_no_length)->fprintffmt"%a[]"pp_typt|T_c_array(t,C_array_length_cstn)->fprintffmt"%a[%s]"pp_typt(Z.to_stringn)|T_c_array(t,C_array_length_expre)->fprintffmt"%a[%a]"pp_typtpp_expre|T_c_functionNone->()|T_c_function(Somef)->fprintffmt"(fun %a)"pp_typf.c_ftype_return|T_c_typedef(typedef)->pp_typfmttypedef.c_typedef_def|T_c_record({c_record_kind=C_struct}asrecord)->fprintffmt"struct %s"record.c_record_org_name|T_c_record({c_record_kind=C_union}asrecord)->fprintffmt"union %s"record.c_record_org_name|T_c_qualified(qual,t)->letl=(ifqual.c_qual_is_constthen["const"]else[])@(ifqual.c_qual_is_volatilethen["volatile"]else[])@(ifqual.c_qual_is_restrictthen["restrict"]else[])inletqual=String.concat" "linfprintffmt"%s %a"qualpp_typt|T_c_enum(enum)->fprintffmt"enum %s"enum.c_enum_org_name|T_c_bitfield(t,size)->fprintffmt"bf %a:%d"pp_typtsize|T_c_builtin_fn->fprintffmt"builtin_fn"|T_c_block_objecttt->Format.fprintffmt"block-object(%a)"pp_typtt|_->defaultfmttyp);register_constant_pp(funnextfmtc->matchcwith|C_c_character(c,k)->fprintffmt"%a'\\x%s'"pp_character_kindk(Z.format"%X"c)|C_c_string(s,k)->fprintffmt"%a\"%s\""pp_character_kindk(String.escapeds)|C_c_invalid->fprintffmt"INVALID"|_->nextfmtc);register_operator_pp(funnextfmtop->matchopwith|O_c_and->pp_print_stringfmt"&&"|O_c_or->pp_print_stringfmt"||"|_->nextfmtop);register_expr_pp(fundefaultfmtexpr->matchekindexprwith|E_c_conditional(cond,body,orelse)->fprintffmt"(%a ? %a : %a)"pp_exprcondpp_exprbodypp_exprorelse|E_c_array_subscript(arr,idx)->fprintffmt"%a[%a]"pp_exprarrpp_expridx|E_c_member_access(rcd,idx,fld)->fprintffmt"%a.%s"pp_exprrcdfld|E_c_function(f)->pp_print_stringfmtf.c_func_org_name|E_c_builtin_function(f)->fprintffmt"builtin %s"f|E_c_builtin_call(f,args)->fprintffmt"builtin %s(%a)"f(pp_print_list~pp_sep:(funfmt()->pp_print_stringfmt", ")pp_expr)args|E_c_arrow_access(p,idx,fld)->fprintffmt"%a->%s"pp_exprpfld|E_c_assign(lval,rval)->fprintffmt"%a = %a"pp_exprlvalpp_exprrval|E_c_compound_assign_->assertfalse|E_c_comma_->assertfalse|E_c_increment_->assertfalse|E_c_address_of(e)->fprintffmt"&%a"pp_expre|E_c_deref(p)->fprintffmt"*%a"pp_exprp|E_c_cast(e,x)->ifx||print_implicit_castthenfprintffmt"(%a) %a"pp_typ(etypexpr)pp_expreelsepp_exprfmte|E_c_statements->fprintffmt"@[<v 4>{@,%a@]@,}"pp_stmts|E_c_var_argse->fprintffmt"__builtin_va_arg(%a)"pp_expre|E_c_block_objecte->fprintffmt"block_object(%a)"pp_expre|E_c_predefined_->assertfalse|E_c_atomic(op,e1,e2)->fprintffmt"__atomic(%i,%a,%a)"oppp_expre1pp_expre2|_->defaultfmtexpr);register_stmt_pp(fundefaultfmtstmt->matchskindstmtwith|S_c_declaration(v,None,_)->fprintffmt"%a %a;"pp_typv.vtyppp_varv|S_c_declaration(v,Someinit,_)->fprintffmt"%a %a = %a;"pp_typv.vtyppp_varvpp_c_initinit|S_c_for(init,cond,it,stmts)->fprintffmt"@[<v 4>for (%a;%a;%a) {@,%a@]@,}"pp_stmtinit(OptionExt.printpp_expr)cond(OptionExt.printpp_expr)itpp_stmtstmts|S_c_do_while(body,cond)->fprintffmt"@[<v 4>do {@,%a@]@, while (%a);"pp_stmtbodypp_exprcond|S_c_switch(cond,body)->fprintffmt"@[<v 4>switch (%a) {@,%a@]@,}"pp_exprcondpp_stmtbody|S_c_return(None,_)->fprintffmt"return;"|S_c_return(Somee,_)->fprintffmt"return %a;"pp_expre|S_c_break_->fprintffmt"break;"|S_c_continue_->fprintffmt"continue;"|S_c_switch_case([{ekind=E_constant(Universal.Ast.C_int_interval(Finitelo,Finitehi))}],_)->fprintffmt"case %s ... %s:"(Z.to_stringlo)(Z.to_stringhi)|S_c_switch_case([e],_)->fprintffmt"case %a:"pp_expre|S_c_switch_case(es,_)->List.iter(fune->fprintffmt"case %a:@,"pp_expre)es|S_c_switch_default_->fprintffmt"default:"|S_c_labell->fprintffmt"%s:"l|S_c_goto(l,_)->fprintffmt"goto %s;"l|S_c_goto_stabs->fprintffmt"@[<v 4>goto_stab {@,%a@]@,};"pp_stmts|S_c_asms->fprintffmt"%s;"s|_->defaultfmtstmt);register_program_pp(fundefaultfmtprg->matchprg.prog_kindwith|Ast.C_programprog->(* Remove empty functions *)letfuns=List.filter(funf->matchf.c_func_bodywith|None->false|Some_->true)prog.c_functionsinfprintffmt"@[<v>";pp_print_list~pp_sep:(funfmt()->fprintffmt"@,@,")(funfmtf->fprintffmt"@[<v 4>%a %s(%a) {@,%a@]@,}"pp_typf.c_func_returnf.c_func_org_name(pp_print_list~pp_sep:(funfmt()->fprintffmt", ")pp_var)f.c_func_parameters(OptionExt.printpp_stmt)f.c_func_body)fmtfuns;fprintffmt"@]"|_->defaultfmtprg);()