def mdoc_typeref(cv): genDoc = { 'DW_TAG_structure_type': lambda cv: bind(mdoc_name(cv), lambda name: unit(P.text("struct ") + name)), 'DW_TAG_typedef': mdoc_name, 'DW_TAG_union_type': mdoc_name, 'DW_TAG_base_type': mdoc_name, 'DW_TAG_const_type': lambda cv: bind(mdie_type(cv), lambda die_type: bind(mdoc_typeref(die_type), lambda typeref: unit(P.text("const ") + typeref))), 'DW_TAG_pointer_type': lambda cv: bind(mdie_type(cv), lambda die_type: bind(mdoc_typeref(die_type), lambda typeref: unit(typeref + P.text("*")))) } # FIXME: which case? if (cv) == (None): return unit(P.text("void")) (_, die) = cv if die.tag in genDoc: return genDoc[die.tag](cv) else: return error('no support for ' + die.tag)
def mdoc_decl_function_struct_type_getter(cv): returnType = mdoc_typeref(cv) # FIXME: use bind name = P.text('default_value_') + value(mdoc_name(cv)) params = P.empty() decl_temp = doc_decl_var(value(returnType), P.text('temp'), P.text('{0, }')) stmt_return = doc_stmt_return(P.text('temp')) block = P.block(decl_temp + P.newline() + stmt_return) return unit(P.text("static ") + doc_decl_function(value(returnType), name, params, block))
def mdoc_typedef_fp(cv): m_subroutine = chain(unit(cv), [mdie_type, mdie_type]) m_params = bind(m_subroutine, lambda ((cu, die)): sequence([mdoc_formalparameter((cu, child)) for child in die.iter_children()]) ) m_docParams = bind(m_params, lambda docs: unit(intersperse(docs, P.comma()))) m_returnType = chain(m_subroutine, [mdie_type, mdoc_typeref]) return bind(m_returnType, lambda ret: bind(m_docParams, lambda params: bind(mdoc_name(cv), lambda name: unit(P.text("typedef ") + ret + P.text(" (*") + name + P.text(") ") + P.text('(') + params + P.text(');')))))
def mdoc_exp_call_default_type_value(cv): (cu, die) = cv if die == None: return error('unexpected DIE(None)') originType = get_origin_type(cu, typeDie) if originType.tag == 'DW_TAG_base_type': return unit(P.text('0')) elif originType.tag == 'DW_TAG_pointer_type': return unit(P.text('0')) # composite(struct) type return bind(mdoc_diename((cu, originType)), lambda name: unit(doc_exp_function_call(P.text('default_value_') + name, [])))
def mdie_type((cu, die)): if 'DW_AT_type' not in die.attributes: m_name = orElse(mdoc_name((cu, die)), unit(P.text("Nil"))) name = value(m_name)[0] return error(name + ':' + die.tag + ' does not have DW_AT_type attribute') offset = die.attributes['DW_AT_type'].value return get_die_by_offset(cu, offset)
def mdoc_structure_type((cu, die)): cv = (cu, die) # struct <name> " {" [<member>] " };" return bind(mdoc_name(cv), lambda name: bind(mdoc_decl_function_struct_type_getter(cv), lambda struct_getter: bind(unit(die.iter_children()), lambda members: bind(sequence([mdoc_member((cu, member)) for member in members]), lambda docMembers: unit(P.text("struct ") + name + P.space() + P.block(intersperse(docMembers, P.newline())) + P.text(";") + P.newline() + struct_getter)))))
def mdoc_stubfunction(cv): return bind(mdoc_name(cv), lambda name: bind(mdie_type(cv), lambda die_type: bind(mdoc_typeref(die_type), lambda return_type: bind(unit([mdoc_formalparameter(cu, child) for child in die.iter_children() if child.tag == 'DW_TAG_formal_parameter']), lambda params: bind(unit(name + P.text("_Callback")), lambda var_functionpointer: bind(unit(P.text("STUBGEN_") + name + P.text("_CALLBACK")), lambda var_type: bind(unit(P.text("(" + var_type + P.text(") 0"))), lambda value: bind(unit(), lambda paramNamesCallback: bind(unit(doc_exp_function_call(var_type, sequence(paramNamesCallback))), lambda call_exp: bind(unit(P.block(P.text("static int stubCallCount = 0;" + P.newline() + (P.text("return ") if die_type else P.empty()) + callExp + P.text(";")))), lambda then_block: bind(unit(), lambda else_block: bind(unit(), lambda if_stmt: unit(doc_decl_function(return_type, name, params, P.block(if_stmt)))))))))))))))
def mdoc_name((cu, die)): if 'DW_AT_name' not in die.attributes: return error(die.tag + ' does not have DW_AT_name attribute') return unit(P.text(die.attributes['DW_AT_name'].value))
def doc_decl_static_var(typeName, name, value): return P.text("static ") + doc_decl_var(typeName, name, value)
def doc_stmt_if(cond, thenPart, elsePart): return P.text("if (") + cond + P.text(") ") + thenPart + P.newline() + P.text("else ") + elsePart
def mdoc_subprogram_legacy(cv): (cu, die) = cv # <return-type> <function-name> <params> name = mdoc_name(cv) typeDie = mdie_type(cv) # TODO: use Monad. if die has no DW_AT_type, return P.text("void "), otherwise typeref(die.type) returnType = mkDoc_typeref(cu, typeDie) if typeDie else P.text("void ") params = [mkDoc_formalparameter(cu, child) for child in die.iter_children() if child.tag == 'DW_TAG_formal_parameter'] paramsCallback = params + P.text("int stubCallCount") varType = P.text("STUBGEN_") + value(name) + P.text("_CALLBACK") decl_typedef_callback = mkDoc_decl_typedef_fp(returnType, paramsCallback, varType) varFp = value(name) + P.text("_Callback") value = P.text("(") + varType + P.text(") 0") decl_var_callback_fp = doc_decl_static_var(varType, varFp, value) # [M doc] paramNamesCallback = [mdoc_name(cu, child) for child in die.iter_children() if child.tag == 'DW_TAG_formal_parameter'] + P.text("stubCallCount++") callExp = mkDoc_exp_function_call(varFp, sequence(paramNamesCallback)) thenBlock = P.block(P.text("static int stubCallCount = 0;") + P.newline() + (P.text("return ") if typeDie else P.empty()) + callExp + P.text(";")) # FIXME: use monad elseBlock = P.block(doc_stmt_return(value(mdoc_exp_call_default_type_value(cv)))) if_stmt = doc_stmt_if(varFp, thenBlock, elseBlock) # return, name, params, block stub_function = doc_decl_function(returnType, name, params, P.block(if_stmt)) # decl callback setter function # void XXX_StubWithCallback (STUBGEN_XXX_CALLBACK cb) setter = name + P.text('_StubWithCallback') setter_param = [varType + P.text(' cb')] setter_body = P.block(varFp + P.text(' = cb;')) setter_function = doc_decl_function(P.text('void'), setter, setter_param, setter_body) return intersperse([decl_typedef_callback, decl_var_callback_fp, stub_function, setter_function], P.newline()) + P.newline()
def mdoc_subprogram(cv): # TODO: refactor and fix return unit(P.text(''))
def mdoc_formalparameter(cv): # may not have name return bind(orElse(mdoc_name(cv), unit(P.space())), lambda name: bind(mdie_type(cv), lambda dieType: bind(mdoc_typeref(dieType), lambda typeref: unit(P.text(typeref) + P.space() + P.text(name)))))
def mdoc_member(cv): return bind(mdoc_name(cv), lambda name: bind(mdie_type(cv), lambda dieType: bind(mdoc_typeref(dieType), lambda typeref: unit(typeref + P.space() + name + P.text(";")))))
def doc_stmt_return(doc): if doc == None: return P.empty() else: return P.text("return ") + doc + P.text(";")
def doc_exp_function_call(function_name, argList): return function_name + P.text("(") + intersperse(argList, P.comma() + P.space()) + P.text(")")
def mkDoc_decl_typedef_fp(returnType, params, typedefName): return P.text("typedef ") + returnType + P.text("(*") + typedefName + P.text(")") + P.text("(") + intersperse(params, P.text(', ')) + P.text(");")
def doc_decl_function(retType, fname, params, body): assert body assert len(body) >= 2 assert body[0] == '{' return retType + P.space() + fname + P.text(" (") + intersperse(params, P.comma()) + P.text(") ") + body
def mdoc_typedef_normal(cv): return bind(mdoc_name(cv), lambda name: bind(mdie_type(cv), lambda die_type: bind(mdoc_typeref(die_type), lambda srcType: unit(P.text("typedef ") + srcType + P.space() + name + P.text(";")))))
def doc_decl_var(typeName, name, value): return typeName + P.space() + name + P.text(" = ") + value + P.text(";")
def mdoc_variable(cv): return bind(mdoc_name(cv), lambda name: bind(mdie_type(cv), lambda dieType: bind(mdoc_typeref(dieType), lambda typeref: unit(P.text(typeref) + P.space() + P.text(name) + P.text(";")))))