inline static unsigned bv_width( const typet &type, const namespacet &ns) { if(type.id()==ID_c_enum_tag) { const typet &t=ns.follow_tag(to_c_enum_tag_type(type)); assert(t.id()==ID_c_enum); return bv_width(t.subtype(), ns); } return unsafe_string2unsigned(type.get_string(ID_width)); }
xmlt xml( const typet &type, const namespacet &ns) { if(type.id()==ID_symbol) return xml(ns.follow(type), ns); xmlt result; if(type.id()==ID_unsignedbv) { result.name="integer"; result.set_attribute("width", to_unsignedbv_type(type).get_width()); } else if(type.id()==ID_signedbv) { result.name="integer"; result.set_attribute("width", to_signedbv_type(type).get_width()); } else if(type.id()==ID_floatbv) { result.name="float"; result.set_attribute("width", to_floatbv_type(type).get_width()); } else if(type.id()==ID_bv) { result.name="integer"; result.set_attribute("width", to_bv_type(type).get_width()); } else if(type.id()==ID_c_bit_field) { result.name="integer"; result.set_attribute("width", to_c_bit_field_type(type).get_width()); } else if(type.id()==ID_c_enum_tag) { // we return the base type return xml(ns.follow_tag(to_c_enum_tag_type(type)).subtype(), ns); } else if(type.id()==ID_fixedbv) { result.name="fixed"; result.set_attribute("width", to_fixedbv_type(type).get_width()); } else if(type.id()==ID_pointer) { result.name="pointer"; result.new_element("subtype").new_element()=xml(type.subtype(), ns); } else if(type.id()==ID_bool) { result.name="boolean"; } else if(type.id()==ID_array) { result.name="array"; result.new_element("subtype").new_element()=xml(type.subtype(), ns); } else if(type.id()==ID_vector) { result.name="vector"; result.new_element("subtype").new_element()=xml(type.subtype(), ns); result.new_element("size").new_element()=xml(to_vector_type(type).size(), ns); } else if(type.id()==ID_struct) { result.name="struct"; const struct_typet::componentst &components= to_struct_type(type).components(); for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { xmlt &e=result.new_element("member"); e.set_attribute("name", id2string(it->get_name())); e.new_element("type").new_element()=xml(it->type(), ns); } } else if(type.id()==ID_union) { result.name="union"; const union_typet::componentst &components= to_union_type(type).components(); for(union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { xmlt &e=result.new_element("member"); e.set_attribute("name", id2string(it->get_name())); e.new_element("type").new_element()=xml(it->type(), ns); } } else result.name="unknown"; return result; }
xmlt xml( const exprt &expr, const namespacet &ns) { xmlt result; const typet &type=ns.follow(expr.type()); if(expr.id()==ID_constant) { if(type.id()==ID_unsignedbv || type.id()==ID_signedbv || type.id()==ID_c_bit_field) { std::size_t width=to_bitvector_type(type).get_width(); result.name="integer"; result.set_attribute("binary", expr.get_string(ID_value)); result.set_attribute("width", width); const typet &underlying_type= type.id()==ID_c_bit_field?type.subtype(): type; bool is_signed=underlying_type.id()==ID_signedbv; std::string sig=is_signed?"":"unsigned "; if(width==config.ansi_c.char_width) result.set_attribute("c_type", sig+"char"); else if(width==config.ansi_c.int_width) result.set_attribute("c_type", sig+"int"); else if(width==config.ansi_c.short_int_width) result.set_attribute("c_type", sig+"short int"); else if(width==config.ansi_c.long_int_width) result.set_attribute("c_type", sig+"long int"); else if(width==config.ansi_c.long_long_int_width) result.set_attribute("c_type", sig+"long long int"); mp_integer i; if(!to_integer(expr, i)) result.data=integer2string(i); } else if(type.id()==ID_c_enum) { result.name="integer"; result.set_attribute("binary", expr.get_string(ID_value)); result.set_attribute("width", type.subtype().get_string(ID_width)); result.set_attribute("c_type", "enum"); mp_integer i; if(!to_integer(expr, i)) result.data=integer2string(i); } else if(type.id()==ID_c_enum_tag) { constant_exprt tmp; tmp.type()=ns.follow_tag(to_c_enum_tag_type(type)); tmp.set_value(to_constant_expr(expr).get_value()); return xml(tmp, ns); } else if(type.id()==ID_bv) { result.name="bitvector"; result.set_attribute("binary", expr.get_string(ID_value)); } else if(type.id()==ID_fixedbv) { result.name="fixed"; result.set_attribute("width", type.get_string(ID_width)); result.set_attribute("binary", expr.get_string(ID_value)); result.data=fixedbvt(to_constant_expr(expr)).to_ansi_c_string(); } else if(type.id()==ID_floatbv) { result.name="float"; result.set_attribute("width", type.get_string(ID_width)); result.set_attribute("binary", expr.get_string(ID_value)); result.data=ieee_floatt(to_constant_expr(expr)).to_ansi_c_string(); } else if(type.id()==ID_pointer) { result.name="pointer"; result.set_attribute("binary", expr.get_string(ID_value)); if(expr.get(ID_value)==ID_NULL) result.data="NULL"; } else if(type.id()==ID_bool) { result.name="boolean"; result.set_attribute("binary", expr.is_true()?"1":"0"); result.data=expr.is_true()?"TRUE":"FALSE"; } else { result.name="unknown"; } } else if(expr.id()==ID_array) { result.name="array"; unsigned index=0; forall_operands(it, expr) { xmlt &e=result.new_element("element"); e.set_attribute("index", index); e.new_element(xml(*it, ns)); index++; }
void c_typecheck_baset::typecheck_type(typet &type) { // we first convert, and then check { ansi_c_convert_typet ansi_c_convert_type(get_message_handler()); ansi_c_convert_type.read(type); ansi_c_convert_type.write(type); } if(type.id()==ID_already_typechecked) { // need to preserve any qualifiers c_qualifierst c_qualifiers(type); c_qualifiers+=c_qualifierst(type.subtype()); bool packed=type.get_bool(ID_C_packed); exprt alignment=static_cast<const exprt &>(type.find(ID_C_alignment)); irept _typedef=type.find(ID_C_typedef); type=type.subtype(); c_qualifiers.write(type); if(packed) type.set(ID_C_packed, true); if(alignment.is_not_nil()) type.add(ID_C_alignment, alignment); if(_typedef.is_not_nil()) type.add(ID_C_typedef, _typedef); return; // done } // do we have alignment? if(type.find(ID_C_alignment).is_not_nil()) { exprt &alignment=static_cast<exprt &>(type.add(ID_C_alignment)); if(alignment.id()!=ID_default) { typecheck_expr(alignment); make_constant(alignment); } } if(type.id()==ID_code) typecheck_code_type(to_code_type(type)); else if(type.id()==ID_array) typecheck_array_type(to_array_type(type)); else if(type.id()==ID_pointer) typecheck_type(type.subtype()); else if(type.id()==ID_struct || type.id()==ID_union) typecheck_compound_type(to_struct_union_type(type)); else if(type.id()==ID_c_enum) typecheck_c_enum_type(type); else if(type.id()==ID_c_enum_tag) typecheck_c_enum_tag_type(to_c_enum_tag_type(type)); else if(type.id()==ID_c_bit_field) typecheck_c_bit_field_type(to_c_bit_field_type(type)); else if(type.id()==ID_typeof) typecheck_typeof_type(type); else if(type.id()==ID_symbol) typecheck_symbol_type(type); else if(type.id()==ID_vector) typecheck_vector_type(to_vector_type(type)); else if(type.id()==ID_custom_unsignedbv || type.id()==ID_custom_signedbv || type.id()==ID_custom_floatbv || type.id()==ID_custom_fixedbv) typecheck_custom_type(type); else if(type.id()==ID_gcc_attribute_mode) { // get that mode irep_idt mode=type.get(ID_size); // A list of all modes ist at // http://www.delorie.com/gnu/docs/gcc/gccint_53.html typecheck_type(type.subtype()); typet underlying_type=type.subtype(); // gcc allows this, but clang doesn't; it's a compiler hint only, // but we'll try to interpret it the GCC way if(underlying_type.id()==ID_c_enum_tag) { underlying_type= follow_tag(to_c_enum_tag_type(underlying_type)).subtype(); assert(underlying_type.id()==ID_signedbv || underlying_type.id()==ID_unsignedbv); } if(underlying_type.id()==ID_signedbv || underlying_type.id()==ID_unsignedbv) { bool is_signed=underlying_type.id()==ID_signedbv; typet result; if(mode=="__QI__") // 8 bits result=is_signed?signed_char_type():unsigned_char_type(); else if(mode=="__byte__") // 8 bits result=is_signed?signed_char_type():unsigned_char_type(); else if(mode=="__HI__") // 16 bits result=is_signed?signed_short_int_type():unsigned_short_int_type(); else if(mode=="__SI__") // 32 bits result=is_signed?signed_int_type():unsigned_int_type(); else if(mode=="__word__") // long int, we think result=is_signed?signed_long_int_type():unsigned_long_int_type(); else if(mode=="__pointer__") // we think this is size_t/ssize_t result=is_signed?signed_size_type():size_type(); else if(mode=="__DI__") // 64 bits { if(config.ansi_c.long_int_width==64) result=is_signed?signed_long_int_type():unsigned_long_int_type(); else { assert(config.ansi_c.long_long_int_width==64); result= is_signed?signed_long_long_int_type():unsigned_long_long_int_type(); } } else if(mode=="__TI__") // 128 bits result=is_signed?gcc_signed_int128_type():gcc_unsigned_int128_type(); else if(mode=="__V2SI__") // vector of 2 ints, deprecated by gcc result= vector_typet( is_signed?signed_int_type():unsigned_int_type(), from_integer(2, size_type())); else if(mode=="__V4SI__") // vector of 4 ints, deprecated by gcc result= vector_typet( is_signed?signed_int_type():unsigned_int_type(), from_integer(4, size_type())); else // give up, just use subtype result=type.subtype(); // save the location result.add_source_location()=type.source_location(); if(type.subtype().id()==ID_c_enum_tag) { const irep_idt &tag_name= to_c_enum_tag_type(type.subtype()).get_identifier(); symbol_tablet::symbolst::iterator entry= symbol_table.symbols.find(tag_name); assert(entry!=symbol_table.symbols.end()); entry->second.type.subtype()=result; } type=result; } else if(underlying_type.id()==ID_floatbv) { typet result; if(mode=="__SF__") // 32 bits result=float_type(); else if(mode=="__DF__") // 64 bits result=double_type(); else if(mode=="__TF__") // 128 bits result=gcc_float128_type(); else if(mode=="__V2SF__") // vector of 2 floats, deprecated by gcc result=vector_typet(float_type(), from_integer(2, size_type())); else if(mode=="__V2DF__") // vector of 2 doubles, deprecated by gcc result=vector_typet(double_type(), from_integer(2, size_type())); else if(mode=="__V4SF__") // vector of 4 floats, deprecated by gcc result=vector_typet(float_type(), from_integer(4, size_type())); else if(mode=="__V4DF__") // vector of 4 doubles, deprecated by gcc result=vector_typet(double_type(), from_integer(4, size_type())); else // give up, just use subtype result=type.subtype(); // save the location result.add_source_location()=type.source_location(); type=result; } else if(underlying_type.id()==ID_complex) { // gcc allows this, but clang doesn't -- see enums above typet result; if(mode=="__SC__") // 32 bits result=float_type(); else if(mode=="__DC__") // 64 bits result=double_type(); else if(mode=="__TC__") // 128 bits result=gcc_float128_type(); else // give up, just use subtype result=type.subtype(); // save the location result.add_source_location()=type.source_location(); type=complex_typet(result); } else { error().source_location=type.source_location(); error() << "attribute mode `" << mode << "' applied to inappropriate type `" << to_string(type) << "'" << eom; throw 0; } } // do a mild bit of rule checking if(type.get_bool(ID_C_restricted) && type.id()!=ID_pointer && type.id()!=ID_array) { error().source_location=type.source_location(); error() << "only a pointer can be 'restrict'" << eom; throw 0; } }
void c_typecheck_baset::typecheck_c_bit_field_type(c_bit_field_typet &type) { typecheck_type(type.subtype()); mp_integer i; { exprt &width_expr=static_cast<exprt &>(type.add(ID_size)); typecheck_expr(width_expr); make_constant_index(width_expr); if(to_integer(width_expr, i)) { error().source_location=type.source_location(); error() << "failed to convert bit field width" << eom; throw 0; } if(i<0) { error().source_location=type.source_location(); error() << "bit field width is negative" << eom; throw 0; } type.set_width(integer2size_t(i)); type.remove(ID_size); } const typet &subtype=follow(type.subtype()); std::size_t sub_width=0; if(subtype.id()==ID_bool) { // This is the 'proper' bool. sub_width=1; } else if(subtype.id()==ID_signedbv || subtype.id()==ID_unsignedbv || subtype.id()==ID_c_bool) { sub_width=to_bitvector_type(subtype).get_width(); } else if(subtype.id()==ID_c_enum_tag) { // These point to an enum, which has a sub-subtype, // which may be smaller or larger than int, and we thus have // to check. const typet &c_enum_type= follow_tag(to_c_enum_tag_type(subtype)); if(c_enum_type.id()==ID_incomplete_c_enum) { error().source_location=type.source_location(); error() << "bit field has incomplete enum type" << eom; throw 0; } sub_width=c_enum_type.subtype().get_int(ID_width); } else { error().source_location=type.source_location(); error() << "bit field with non-integer type: " << to_string(subtype) << eom; throw 0; } if(i>sub_width) { error().source_location=type.source_location(); error() << "bit field (" << i << " bits) larger than type (" << sub_width << " bits)" << eom; throw 0; } }
const boolbv_widtht::entryt &boolbv_widtht::get_entry(const typet &type) const { // check cache first std::pair<cachet::iterator, bool> cache_result= cache.insert(std::pair<typet, entryt>(type, entryt())); entryt &entry=cache_result.first->second; if(!cache_result.second) // found! return entry; entry.total_width=0; const irep_idt type_id=type.id(); if(type_id==ID_struct) { const struct_typet::componentst &components= to_struct_type(type).components(); std::size_t offset=0; entry.members.resize(components.size()); for(std::size_t i=0; i<entry.members.size(); i++) { std::size_t sub_width=operator()(components[i].type()); entry.members[i].offset=offset; entry.members[i].width=sub_width; offset+=sub_width; } entry.total_width=offset; } else if(type_id==ID_union) { const union_typet::componentst &components= to_union_type(type).components(); entry.members.resize(components.size()); std::size_t max_width=0; for(std::size_t i=0; i<entry.members.size(); i++) { std::size_t sub_width=operator()(components[i].type()); entry.members[i].width=sub_width; max_width=std::max(max_width, sub_width); } entry.total_width=max_width; } else if(type_id==ID_bool) entry.total_width=1; else if(type_id==ID_c_bool) { entry.total_width=to_c_bool_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_signedbv) { entry.total_width=to_signedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_unsignedbv) { entry.total_width=to_unsignedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_floatbv) { entry.total_width=to_floatbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_fixedbv) { entry.total_width=to_fixedbv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_bv) { entry.total_width=to_bv_type(type).get_width(); assert(entry.total_width!=0); } else if(type_id==ID_verilogbv) { // we encode with two bits entry.total_width=type.get_unsigned_int(ID_width)*2; assert(entry.total_width!=0); } else if(type_id==ID_range) { mp_integer from=string2integer(type.get_string(ID_from)), to=string2integer(type.get_string(ID_to)); mp_integer size=to-from+1; if(size>=1) { entry.total_width=integer2unsigned(address_bits(size)); assert(entry.total_width!=0); } } else if(type_id==ID_array) { const array_typet &array_type=to_array_type(type); std::size_t sub_width=operator()(array_type.subtype()); mp_integer array_size; if(to_integer(array_type.size(), array_size)) { // we can still use the theory of arrays for this entry.total_width=0; } else { mp_integer total=array_size*sub_width; if(total>(1<<30)) // realistic limit throw "array too large for flattening"; entry.total_width=integer2unsigned(total); } } else if(type_id==ID_vector) { const vector_typet &vector_type=to_vector_type(type); std::size_t sub_width=operator()(vector_type.subtype()); mp_integer vector_size; if(to_integer(vector_type.size(), vector_size)) { // we can still use the theory of arrays for this entry.total_width=0; } else { mp_integer total=vector_size*sub_width; if(total>(1<<30)) // realistic limit throw "vector too large for flattening"; entry.total_width=integer2unsigned(vector_size*sub_width); } } else if(type_id==ID_complex) { std::size_t sub_width=operator()(type.subtype()); entry.total_width=integer2unsigned(2*sub_width); } else if(type_id==ID_code) { } else if(type_id==ID_enum) { // get number of necessary bits std::size_t size=type.find(ID_elements).get_sub().size(); entry.total_width=integer2unsigned(address_bits(size)); assert(entry.total_width!=0); } else if(type_id==ID_c_enum) { // these have a subtype entry.total_width=type.subtype().get_unsigned_int(ID_width); assert(entry.total_width!=0); } else if(type_id==ID_incomplete_c_enum) { // no width } else if(type_id==ID_pointer || type_id==ID_reference) { entry.total_width=config.ansi_c.pointer_width; } else if(type_id==ID_symbol) entry=get_entry(ns.follow(type)); else if(type_id==ID_struct_tag) entry=get_entry(ns.follow_tag(to_struct_tag_type(type))); else if(type_id==ID_union_tag) entry=get_entry(ns.follow_tag(to_union_tag_type(type))); else if(type_id==ID_c_enum_tag) entry=get_entry(ns.follow_tag(to_c_enum_tag_type(type))); else if(type_id==ID_c_bit_field) { entry.total_width=to_c_bit_field_type(type).get_width(); } return entry; }
mp_integer alignment(const typet &type, const namespacet &ns) { // is the alignment given? const exprt &given_alignment= static_cast<const exprt &>(type.find(ID_C_alignment)); if(given_alignment.is_not_nil()) { mp_integer a_int; if(!to_integer(given_alignment, a_int)) return a_int; // we trust it blindly, no matter how nonsensical } // compute default if(type.id()==ID_array) { return alignment(type.subtype(), ns); } else if(type.id()==ID_struct || type.id()==ID_union) { const struct_union_typet::componentst &components= to_struct_union_type(type).components(); mp_integer result=1; // get the max // (should really be the smallest common denominator) for(struct_union_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) result=std::max(result, alignment(it->type(), ns)); return result; } else if(type.id()==ID_unsignedbv || type.id()==ID_signedbv || type.id()==ID_fixedbv || type.id()==ID_floatbv || type.id()==ID_c_bool) { unsigned width=to_bitvector_type(type).get_width(); return width%8?width/8+1:width/8; } else if(type.id()==ID_c_enum) { return alignment(type.subtype(), ns); } else if(type.id()==ID_c_enum_tag) { return alignment(ns.follow_tag(to_c_enum_tag_type(type)), ns); } else if(type.id()==ID_pointer) { unsigned width=config.ansi_c.pointer_width; return width%8?width/8+1:width/8; } else if(type.id()==ID_symbol) return alignment(ns.follow(type), ns); return 1; }
json_objectt json( const typet &type, const namespacet &ns) { if(type.id()==ID_symbol) return json(ns.follow(type), ns); json_objectt result; if(type.id()==ID_unsignedbv) { result["name"]=json_stringt("integer"); result["width"]= json_numbert(i2string(to_unsignedbv_type(type).get_width())); } else if(type.id()==ID_signedbv) { result["name"]=json_stringt("integer"); result["width"]=json_numbert(i2string(to_signedbv_type(type).get_width())); } else if(type.id()==ID_floatbv) { result["name"]=json_stringt("float"); result["width"]=json_numbert(i2string(to_floatbv_type(type).get_width())); } else if(type.id()==ID_bv) { result["name"]=json_stringt("integer"); result["width"]=json_numbert(i2string(to_bv_type(type).get_width())); } else if(type.id()==ID_c_bit_field) { result["name"]=json_stringt("integer"); result["width"]= json_numbert(i2string(to_c_bit_field_type(type).get_width())); } else if(type.id()==ID_c_enum_tag) { // we return the base type return json(ns.follow_tag(to_c_enum_tag_type(type)).subtype(), ns); } else if(type.id()==ID_fixedbv) { result["name"]=json_stringt("fixed"); result["width"]=json_numbert(i2string(to_fixedbv_type(type).get_width())); } else if(type.id()==ID_pointer) { result["name"]=json_stringt("pointer"); result["subtype"]=json(type.subtype(), ns); } else if(type.id()==ID_bool) { result["name"]=json_stringt("boolean"); } else if(type.id()==ID_array) { result["name"]=json_stringt("array"); result["subtype"]=json(type.subtype(), ns); } else if(type.id()==ID_vector) { result["name"]=json_stringt("vector"); result["subtype"]=json(type.subtype(), ns); result["size"]=json(to_vector_type(type).size(), ns); } else if(type.id()==ID_struct) { result["name"]=json_stringt("struct"); json_arrayt &members=result["members"].make_array(); const struct_typet::componentst &components= to_struct_type(type).components(); for(const auto & it : components) { json_objectt &e=members.push_back().make_object(); e["name"]=json_stringt(id2string(it.get_name())); e["type"]=json(it.type(), ns); } } else if(type.id()==ID_union) { result["name"]=json_stringt("union"); json_arrayt &members=result["members"].make_array(); const union_typet::componentst &components= to_union_type(type).components(); for(const auto & it : components) { json_objectt &e=members.push_back().make_object(); e["name"]=json_stringt(id2string(it.get_name())); e["type"]=json(it.type(), ns); } } else result["name"]=json_stringt("unknown"); return result; }
json_objectt json( const exprt &expr, const namespacet &ns) { json_objectt result; const typet &type=ns.follow(expr.type()); if(expr.id()==ID_constant) { if(type.id()==ID_unsignedbv || type.id()==ID_signedbv || type.id()==ID_c_bit_field) { std::size_t width=to_bitvector_type(type).get_width(); result["name"]=json_stringt("integer"); result["binary"]=json_stringt(expr.get_string(ID_value)); result["width"]=json_numbert(i2string(width)); const typet &underlying_type= type.id()==ID_c_bit_field?type.subtype(): type; bool is_signed=underlying_type.id()==ID_signedbv; std::string sig=is_signed?"":"unsigned "; if(width==config.ansi_c.char_width) result["c_type"]=json_stringt(sig+"char"); else if(width==config.ansi_c.int_width) result["c_type"]=json_stringt(sig+"int"); else if(width==config.ansi_c.short_int_width) result["c_type"]=json_stringt(sig+"short int"); else if(width==config.ansi_c.long_int_width) result["c_type"]=json_stringt(sig+"long int"); else if(width==config.ansi_c.long_long_int_width) result["c_type"]=json_stringt(sig+"long long int"); mp_integer i; if(!to_integer(expr, i)) result["data"]=json_stringt(integer2string(i)); } else if(type.id()==ID_c_enum) { result["name"]=json_stringt("integer"); result["binary"]=json_stringt(expr.get_string(ID_value)); result["width"]=json_numbert(type.subtype().get_string(ID_width)); result["c_type"]=json_stringt("enum"); mp_integer i; if(!to_integer(expr, i)) result["data"]=json_stringt(integer2string(i)); } else if(type.id()==ID_c_enum_tag) { constant_exprt tmp; tmp.type()=ns.follow_tag(to_c_enum_tag_type(type)); tmp.set_value(to_constant_expr(expr).get_value()); return json(tmp, ns); } else if(type.id()==ID_bv) { result["name"]=json_stringt("bitvector"); result["binary"]=json_stringt(expr.get_string(ID_value)); } else if(type.id()==ID_fixedbv) { result["name"]=json_stringt("fixed"); result["width"]=json_numbert(type.get_string(ID_width)); result["binary"]=json_stringt(expr.get_string(ID_value)); result["data"]= json_stringt(fixedbvt(to_constant_expr(expr)).to_ansi_c_string()); } else if(type.id()==ID_floatbv) { result["name"]=json_stringt("float"); result["width"]=json_numbert(type.get_string(ID_width)); result["binary"]=json_stringt(expr.get_string(ID_value)); result["data"]= json_stringt(ieee_floatt(to_constant_expr(expr)).to_ansi_c_string()); } else if(type.id()==ID_pointer) { result["name"]=json_stringt("pointer"); result["binary"]=json_stringt(expr.get_string(ID_value)); if(expr.get(ID_value)==ID_NULL) result["data"]=json_stringt("NULL"); } else if(type.id()==ID_bool) { result["name"]=json_stringt("boolean"); result["binary"]=json_stringt(expr.is_true()?"1":"0"); result["data"]=jsont::json_boolean(expr.is_true()); } else { result["name"]=json_stringt("unknown"); } } else if(expr.id()==ID_array) { result["name"]=json_stringt("array"); json_arrayt &elements=result["elements"].make_array(); unsigned index=0; forall_operands(it, expr) { json_objectt &e=elements.push_back().make_object(); e["index"]=json_numbert(i2string(index)); e["value"]=json(*it, ns); index++; }