drdecnam.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,033 行 · 第 1/5 页

C
2,033
字号
        dr_handle containing_entry;

        containing_entry = DWRReadReference( tmp_abbrev, tmp_entry );
        if( containing_entry != DW_TAG_padding ) {
            GetContaining( &decname->var_bas, containing_entry );
        }
    }

    tmp_abbrev = loc->abbrev_cr;
    tmp_entry = loc->entry_cr;
    if( DWRScanForAttrib( &tmp_abbrev, &tmp_entry, DW_AT_type ) == DW_AT_type ) {
        dr_handle type_entry = DWRReadReference( tmp_abbrev, tmp_entry );

        type_entry =  SkipPCH( type_entry );
        if( type_entry != DW_TAG_padding ) {
            FillLoc( &type_loc, type_entry );
            DecorateType( decname, &type_loc, DW_TAG_padding );
        }
    }

    parms = StartFunctionParms( loc );

    if( decname->func_bas.tail == NULL ) {
        decname->func_bas.head = parms.head;
        decname->func_bas.tail = parms.tail;
    } else {
        decname->func_bas.tail->next = parms.head;
        decname->func_bas.tail = parms.tail;
    }

    return( decname );
}

static List_T StartFunctionParms( Loc_T *loc )
/********************************************/
{
    List_T      ret = { NULL, NULL, LIST_TAIL };
    List_T      add_parm;
    bool        first_time = TRUE;
    Loc_T       parm_loc;

    ListConcat( &ret, FuncStartKwd );

    if( loc->child == DW_CHILDREN_yes ) {
        dr_handle tmp_entry;
        dr_handle tmp_abbrev;

        tmp_entry = loc->entry_cr;
        tmp_abbrev = loc->abbrev_cr;
        DWRSkipAttribs( tmp_abbrev, &tmp_entry );

        FillLoc( &parm_loc, tmp_entry );

        while( parm_loc.entry_st != 0 ) {

            add_parm = DecorateParameter( &parm_loc );

            if( add_parm.head != NULL ) {
                if( first_time ) {
                    first_time = FALSE;
                    ListConcat( &ret, SpaceKwd );
                } else {
                    ListConcat( &ret, ParmSepKwd );
                }

                if( ret.tail == NULL ) {
                    ret.head = add_parm.head;
                    ret.tail = add_parm.tail;
                } else {
                    ret.tail->next = add_parm.head;
                    ret.tail = add_parm.tail;
                }
            }
        }
    }

    if( !first_time ) {
        ListConcat( &ret, SpaceKwd );
    }

    ListConcat( &ret, FuncEndKwd );

    return( ret );
}

/*
 * decorate a function's formal parameters.
 * loc->entry_st points to a child entry.  DecorateParameter considers
 * this child -- if it is a parameter, it decorates it and returns a List_T.
 * otherwise, it checks siblings. loc is always updated to point to
 * the next sibling. If there are no more siblings, it sets
 * loc->entry_st to 0.
 */

static List_T DecorateParameter( Loc_T *loc )
/*******************************************/
{
    List_T          ret = { NULL, NULL };
    BrokenName_T    decstruct = Empty_Broken_Name;

    dr_handle       tmp_abbrev;
    dr_handle       tmp_entry;

    tmp_entry = loc->entry_cr;
    tmp_abbrev = loc->abbrev_cr;

    while( loc->tag != DW_TAG_unspecified_parameters &&
             loc->tag != DW_TAG_formal_parameter && loc->abbrev_st != 0 ) {

        if( loc->child ) {
            DWRSkipChildren( &tmp_abbrev, &tmp_entry );
        } else {
            DWRSkipAttribs( tmp_abbrev, &tmp_entry );
        }
        FillLoc( loc, tmp_entry );
        tmp_abbrev = loc->abbrev_cr;
        tmp_entry = loc->entry_cr;
    }

    if( loc->abbrev_st != 0 ) {
        switch( loc->tag ) {
        case DW_TAG_unspecified_parameters:
            ListConcat( &ret, UnspecParamKwd );
            break;

        case DW_TAG_formal_parameter:
            DecorateVariable( &decstruct, loc );
            ret = FormList( &decstruct );
            ret.end = LIST_TAIL;
            EndNode( &ret, FALSE, 0, DR_SYM_NOT_SYM );
            break;

        default:
            DWREXCEPT( DREXCEP_DWARF_LIB_FAIL );
        }

        tmp_abbrev = loc->abbrev_cr;
        tmp_entry = loc->entry_cr;
        if( loc->child ) {
            DWRSkipChildren( &tmp_abbrev, &tmp_entry );
        } else {
            DWRSkipAttribs( tmp_abbrev, &tmp_entry );
        }
        FillLoc( loc, tmp_entry );
    }

    return( ret );
}

/*
 * decorate a type.
 * prev_tag contains the
 * previous tag that was handled by the type.  This is needed for the
 * pointer to subroutine type -- it needs to know if it resolves to a pointer
 * to a subroutine, or a subroutine type itself.
 *
 * WARNING -- this changes the contents of loc.
 */

static BrokenName_T *DecorateType( BrokenName_T *decname, Loc_T *loc,
                                   dr_handle prev_tag )
/*******************************************************************/
{
    dr_handle   tmp_entry;
    dr_handle   tmp_abbrev;
    dr_handle   next_die;
    String      typename;
    bool        done = FALSE;   /* true when the end of the type chain is reached */

    tmp_abbrev = loc->abbrev_cr;
    tmp_entry = loc->entry_cr;

    switch( loc->tag ) {
    case DW_TAG_base_type:
    case DW_TAG_typedef:
        GrabName( tmp_abbrev, tmp_entry, &typename );

        ListConcat( &( decname->type_bas ), SpaceKwd );
        if( loc->tag == DW_TAG_typedef ) {
            EndNode( &( decname->type_bas ), TRUE, loc->entry_st, DR_SYM_TYPEDEF );
            ListConcat( &( decname->type_bas ), typename );
            EndNode( &( decname->type_bas ), FALSE, 0, DR_SYM_NOT_SYM );
        } else {
            ListConcat( &( decname->type_bas ), typename );
        }
        if( prev_tag == DW_TAG_const_type || prev_tag == DW_TAG_volatile_type ) {
            SwapModifier( decname );
        }
        DWRFREE( typename.s );
        done = TRUE;

        break;

    case DW_TAG_const_type:
        if( prev_tag != DW_TAG_const_type && prev_tag != DW_TAG_volatile_type ) {
            EndNode( &( decname->type_elg ), FALSE, 0, DR_SYM_NOT_SYM );
        }
        AddTypeString( decname, ConstKwd, TYPE_ELG );
        break;

    case DW_TAG_volatile_type:
        if( prev_tag != DW_TAG_const_type && prev_tag != DW_TAG_volatile_type ) {
            EndNode( &( decname->type_elg ), FALSE, 0, DR_SYM_NOT_SYM );
        }
        AddTypeString( decname, VolatileKwd, TYPE_ELG );
        break;

    case DW_TAG_pointer_type:
        EndNode( &( decname->type_ptr ), FALSE, 0, DR_SYM_NOT_SYM );
        AddTypeString( decname, PtrKwd, TYPE_PTR );
        break;

    case DW_TAG_reference_type:
        EndNode( &( decname->type_ptr ), FALSE, 0, DR_SYM_NOT_SYM );
        AddTypeString( decname, RefKwd, TYPE_PTR );
        break;

    case DW_TAG_ptr_to_member_type:
        DecoratePtrToMember( decname, loc );
        break;

    case DW_TAG_WATCOM_address_class_type:
        if( prev_tag != DW_TAG_pointer_type ) {
            EndNode( &( decname->type_ptr ), FALSE, 0, DR_SYM_NOT_SYM );
        }
        AddPtrModifier( decname, loc );
        break;

    case DW_TAG_enumeration_type:
        DecorateCompoundType( decname, loc, EnumKwd, DR_SYM_ENUM );
        break;

    case DW_TAG_class_type:
        DecorateCompoundType( decname, loc, ClassKwd, DR_SYM_CLASS );
        break;

    case DW_TAG_structure_type:
        DecorateCompoundType( decname, loc, StructKwd, DR_SYM_CLASS );
        break;

    case DW_TAG_union_type:
        DecorateCompoundType( decname, loc, UnionKwd, DR_SYM_CLASS );
        break;

    case DW_TAG_array_type:
        DecorateArray( decname, loc );
        done = TRUE;
        break;

    case DW_TAG_subroutine_type:
        DecSubroutineType( decname, loc, prev_tag );
        break;

    default:
        DWREXCEPT ( DREXCEP_DWARF_LIB_FAIL );
    }

    if( !done ) {
        tmp_abbrev = loc->abbrev_cr;
        tmp_entry = loc->entry_cr;
        if( DWRScanForAttrib( &tmp_abbrev, &tmp_entry, DW_AT_type ) == DW_AT_type ) {
            next_die = DWRReadReference( tmp_abbrev, tmp_entry );
            next_die =  SkipPCH( next_die );
            if( next_die != DW_TAG_padding ) {
                if( loc->tag == DW_TAG_WATCOM_address_class_type ) {
                    prev_tag = prev_tag;
                } else {
                    prev_tag = loc->tag;
                }
                FillLoc( loc, next_die );
                DecorateType( decname, loc, prev_tag );
            }
        }
    }

    return( decname );
}

/*
 * take the last node from type_bas and put it at the end of type_plg.
 * this is used for constant and volatile modifiers formed as right
 * associative expressions.
 */
static void SwapModifier( BrokenName_T *decname )
/***********************************************/
{
    Node_T  target;

    target = DeleteTail( &( decname->type_elg ) );

    if( target == NULL ) {
        DWREXCEPT( DREXCEP_DWARF_LIB_FAIL );
    }

    if( decname->type_plg.head == NULL || decname->type_plg.tail == NULL ) {
        decname->type_plg.head = target;
        decname->type_plg.tail = target;
    } else {
        target->next = decname->type_plg.head;
        decname->type_plg.head = target;
    }
    strrev( target->buf.s );
}

static BrokenName_T *AddPtrModifier( BrokenName_T *decname, Loc_T *loc )
/**********************************************************************/
{
    dr_handle   tmp_entry;
    dr_handle   tmp_abbrev;
    unsigned_32 addr_class;
    bool        spaceit = FALSE;

    tmp_entry = loc->entry_cr;
    tmp_abbrev = loc->abbrev_cr;
    if( DWRScanForAttrib( &tmp_abbrev,  &tmp_entry, DW_AT_address_class )
        ==  DW_AT_address_class ) {

        if( decname->type_ptr.head != NULL ) {
            spaceit = TRUE;
        }

        addr_class = DWRReadConstant( tmp_abbrev, tmp_entry );
        ListConcat( &( decname->type_ptr ), *AddressClasses[ addr_class] );

        if( spaceit ) {
            ListConcat( &( decname->type_ptr ), SpaceKwd );
        }
    }

    return( decname );
}

static BrokenName_T *DecSubroutineType( BrokenName_T *decname, Loc_T *loc,
                                         dr_handle prev_tag )
/************************************************************************/
{
    List_T  parms;
    Node_T  target;

    if( prev_tag == DW_TAG_pointer_type ) {
        target = DeleteTail( &( decname->type_ptr ) );
        ListConcat( &( decname->var_plg ), SpaceKwd );
        ListAdd( &( decname->var_plg ), target );
        ListConcat( &( decname->var_plg ), FuncStartKwd );
    } else {
        ListConcat( &( decname->var_plg ), FuncStartKwd );
    }

    ListConcat( &( decname->var_elg ), FuncEndKwd );

    parms = StartFunctionParms( loc );

    if( decname->func_bas.tail == NULL ) {
        decname->func_bas.head = parms.head;
        decname->func_bas.tail = parms.tail;
    } else {
        decname->func_bas.tail->next = parms.head;
        decname->func_bas.tail = parms.tail;
    }

    return( decname );
}

static void AddTypeString( BrokenName_T *dn, String Kwd,
                           TypeSide_T ts)
/******************************************************/
{
    List_T  *list;

    switch( ts ) {
    case TYPE_PLG:
        list = &(dn->type_plg);
        break;

    case TYPE_BAS:
        list = &(dn->type_bas);
        break;

    case TYPE_PTR:
        list = &(dn->type_ptr);
        break;

    case TYPE_ELG:
        list = &(dn->type_elg);
        break;

    default:
        DWREXCEPT( DREXCEP_DWARF_LIB_FAIL );
    }

    ListConcat( list, Kwd );
}


/*
 * decorate a union, struct or class.
 */

BrokenName_T *DecorateCompoundType( BrokenName_T *decname, Loc_T *loc,
                                     String Kwd, dr_sym_type symtype )
/********************************************************************/
{
    String  typename;

    GrabName( loc->abbrev_cr, loc->entry_cr, &typename );

    ListConcat( &( decname->type_bas ), SpaceKwd );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?