dwmakeab.c

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

C
889
字号
        DW_TAG_subprogram,
        DECL | AB_ARTIFICIAL,
        {
            DW_AT_accessibility,        DW_FORM_data1,
            DW_AT_type,                 DW_FORM_ref4,
            DW_AT_name,                 DW_FORM_string,
            DW_AT_declaration,          DW_FORM_flag,
            DW_AT_inline,               DW_FORM_data1,
            DW_AT_segment,              DW_FORM_block1,
            DW_AT_location,             DW_FORM_block1,
            0
        }
    },
#endif
    {
        "AB_MEMFUNCDECL",
        DW_TAG_subprogram,
        DECL | AB_ARTIFICIAL,
        {
            DW_AT_accessibility,        DW_FORM_data1,
            DW_AT_type,                 DW_FORM_ref4,
            DW_AT_name,                 DW_FORM_string,
            DW_AT_declaration,          DW_FORM_flag,
            DW_AT_inline,               DW_FORM_data1,
            0
        }
    },
    {
        "AB_VIRTMEMFUNCDECL",
        DW_TAG_subprogram,
        DECL,
        {
            DW_AT_accessibility,        DW_FORM_data1,
            DW_AT_type,                 DW_FORM_ref4,
            DW_AT_name,                 DW_FORM_string,
            DW_AT_declaration,          DW_FORM_flag,
            DW_AT_inline,               DW_FORM_data1,
            DW_AT_virtuality,           DW_FORM_data1,
            DW_AT_vtable_elem_location, DW_FORM_block1,
            0
        }
    },
    {
        "AB_FORMAL_PARM_TYPE",
        DW_TAG_formal_parameter,
        DECL | AB_NAME,
        {
            DW_AT_type,                 DW_FORM_ref4,
            0
        }
    },
    {
        "AB_FORMAL_PARAMETER",
        DW_TAG_formal_parameter,
        DECL,
        {
            DW_AT_name,                 DW_FORM_string,
            DW_AT_location,             DW_FORM_block1,
            DW_AT_WATCOM_parm_entry,    DW_FORM_block1,
            DW_AT_type,                 DW_FORM_ref4,
            0
        }
    },

    {
        "AB_FORMAL_PARAMETER_WITH_DEFAULT",
        DW_TAG_formal_parameter,
        DECL,
        {
            DW_AT_default_value,        DW_FORM_block1,
            DW_AT_name,                 DW_FORM_string,
            DW_AT_location,             DW_FORM_block1,
            DW_AT_WATCOM_parm_entry,    DW_FORM_block1,
            DW_AT_type,                 DW_FORM_ref4,
            0
        }
    },

    {
        "AB_ELLIPSIS",
        DW_TAG_unspecified_parameters,
        DECL,
        {
            0
        }
    },

    {
        "AB_LABEL",
        DW_TAG_label,
        AB_NAME | AB_START_SCOPE | AB_SEGMENT,
        {
            DW_AT_low_pc,               DW_FORM_addr,
            0
        }
    },

    {
        "AB_VARIABLE",
        DW_TAG_variable,
        DECL | COMMON_NBITS | AB_MEMBER | AB_SEGMENT
            | AB_DECLARATION,
        {
            DW_AT_external,             DW_FORM_flag,
            DW_AT_artificial,           DW_FORM_flag,
            DW_AT_name,                 DW_FORM_string,
            DW_AT_location,             DW_FORM_block1,
            DW_AT_type,                 DW_FORM_ref4,
            0
        }
    },

    {
        "AB_CONSTANT",
        DW_TAG_variable,
        DECL | COMMON_NBITS | AB_MEMBER,
        {
            DW_AT_external,             DW_FORM_flag,
            DW_AT_const_value,          DW_FORM_block1,
            DW_AT_name,                 DW_FORM_string,
            DW_AT_type,                 DW_FORM_ref4,
            0
        }
    },
    {
        "AB_NAMELIST",
        DW_TAG_namelist,
        DECL | AB_SIBLING,
        {
            DW_AT_name,                 DW_FORM_string,
            0
        }
    },
    {
        "AB_NAMELIST_ITEM",
        DW_TAG_namelist_item,
        DECL,
        {
            DW_AT_namelist_item,        DW_FORM_ref4,
            0
        }
    },

    {
        "AB_COMMON_INCLUSION",
        DW_TAG_common_inclusion,
        DECL,
        {
            DW_AT_common_reference,     DW_FORM_ref4,
            0
        }
    },
    {
        "AB_NAMESPACE",
        DW_TAG_WATCOM_namespace,
        DECL | AB_NAME | AB_SIBLING,
        {
            0
        }
    },
};
#define AB_MAX  ( sizeof( abbrevInfo ) / sizeof( abbrevInfo[0] ) )


typedef struct {
    uint_32             data_offset;
    uint_32             data_len;
} extra_info;

extra_info abbrevExtra[ AB_MAX ];


void emitEnum(
    FILE *                      fp )
{
    uint                        u;

    fprintf( fp, "enum {\n    AB_PADDING,\n" );
    for( u = 0; u < AB_MAX; ++u ) {
        fprintf( fp, "    %s,\n", abbrevInfo[ u ].name );
    }
    fprintf( fp, "    AB_MAX\n};" );
}

size_t topOfEncoding;
uint_8 encodingBuf[ AB_MAX * MAX_LEB128 * MAX_CODES ];
uint_8 tempEncoding[ MAX_LEB128 * MAX_CODES ];

size_t addToEncoding(
    size_t                      this_size )
{
    size_t                      anchor;
    size_t                      dest;
    size_t                      src;

    if( this_size == 0 ) {
        return( 0 );
    }
    /*
        Scan the sequences of bytes we have so far, and see if
        we can overlay this one on top of another one.
    */
    dest = 0;
    src = 0;
    anchor = ~0;
    while( dest < topOfEncoding ) {
        if( encodingBuf[ dest ] != tempEncoding[ src ] ) {
            src = 0;
            if( anchor == ~0 ) {
                ++dest;
            } else {
                dest = anchor + 1;
                anchor = ~0;
            }
        } else {
            if( anchor == ~0 ) {
                anchor = dest;
            }
            ++dest;
            ++src;
            if( src == this_size ) {
                /* we've found a substring that matches exactly */
                return( anchor );
            }
        }
    }
    /*
        At this point we know that src bytes of the source string match
        the last src bytes of the destination string.
    */
    memcpy( &encodingBuf[ dest ], &tempEncoding[ src ], this_size - src );
    topOfEncoding += this_size - src;
    if( anchor == ~0 ) {
        return( dest );
    }
    return( anchor );
}


void emitEncodings(
    FILE *                      fp )
{
/*
    The plan is to take the above table and compress it into a smaller
    form.  The first obvious thing is to do the ULEB128 encodings now
    since they are compile-time constant, and much smaller.
*/
    uint                        u;
    uint_8 *                    end;
    uint_8 *                    p;
    uint_32 const*              data;

    topOfEncoding = 0;
    for( u = 0; u < AB_MAX; ++u ) {
        /*
            Determine what the sequence of bytes is for this abbreviation
        */
        end = tempEncoding;
        for( data = abbrevInfo[ u ].data; *data; ++data ) {
            end = ULEB128( end, *data );
        }
        abbrevExtra[ u ].data_len = end - tempEncoding;
        abbrevExtra[ u ].data_offset = addToEncoding( end - tempEncoding );
    }

    fprintf( fp, "\nstatic const uint_8 encodings[] = {\n    /* 0x00 */ " );
    end = encodingBuf + topOfEncoding;
    p = encodingBuf;
    for(;;) {
        fprintf( fp, "0x%02x", *p );
        ++p;
        if( p == end ) break;
        fprintf( fp, "," );
        if( ( p - encodingBuf ) % 8 == 0 ) {
            fprintf( fp, "\n    /* 0x%02x */ ", p - encodingBuf );
        }
    }
    fprintf( fp, "\n};\n\n" );
}


uint CountBits(
    uint_32                     value )
{
    uint                        number;

    number = 0;
    while( value ) {
        ++number;
        value &= value - 1;
    }
    return( number );
}


/*
    We must have a way to determine if a particular abbreviation has
    been emitted.

    An abbrev_code has a base portion that corresponds to the entries
    in abbrevInfo.  Then any bit from valid_mask can be set on
    to add attribute/forms to the abbreviation.

    Let 0 <= u < AB_MAX.

    Let V be the vector space GF(2)**32.  i.e. a vector space with
    32 dimensions, each of which is either 0 or 1.

    Then abbrevInfo[u].valid_mask can be considered to be a
    projection of V onto a subspace, call that subspace W(u).
    There are 2**dim(W(u)) possible vectors in W(u).  This is the
    number of bits we will require to represent each of the
    vectors in W(u).

    For example, suppose abbrevInfo[u].valid_mask == 0xa. Then

        W(u) = { 0b0000, 0b0010, 0b1000, 0b1010 }.

    Note that { 0b0010, 0b1000 } forms a basis for W(u), hence
    dim(W(u)) = 2.

    Let K(i) be the binary representation of the set of
    integers { 0, 1, ..., 2**i - 1 }.  Then K(i) can be considered
    a subspace of V. There is a natural mapping from W(u) to K(dim(W(u))).
    Using the W(u) example from above, we would map:

        W(u)    -->     K(2)
        0b0000          0b00
        0b0010          0b01
        0b1000          0b10
        0b1010          0b11

    The mapping basically "delete"s the co-ordinates of V that are
    not used in W(u).  We'll use this method to represent when an
    abbreviation has been output.  Basically we'll just concatenate
    all the spaces K(dim(W(u))) together for all u into a bitvector X.

    Like this:

                X =      x          K( dim( W( u ) ) )
                    0 <= u < AB_MAX

    (The 'x' indicates cross-product.)

    Isn't linear algebra wonderful? :)

    It would be slow for us to have to calculate the offset of a
    particular u in X every time, so we'll precalculate it for each u
    and store it in a structure.

    DJG
*/
/*
   KLUDGE ALERT!  total starts are LAST_LINKER_ABBREV instead of zero to keep
   the abbrev codes that the linker generates separate from the abbrev codes
   generated by the writing library
*/
uint_32 emitInfo(
    FILE *                      fp )
{
    uint_32                     total;
    uint                        u;

    fprintf( fp,"\nstatic const struct abbrev_info {\n"
                "    abbrev_code        valid_mask;\n"
                "    uint_16            bit_index;\n"
                "    uint_8             data_offset;\n"
                "    uint_8             data_len;\n"
                "    uint_16            tag;\n"
                "} abbrevInfo[] = {\n" );
    total = LAST_LINKER_ABBREV + 1;     // FIXME KLUDGE! see above
    u = 0;
    for(;;) {
        fprintf( fp, "/*%-32s*/{ 0x%08lx, 0x%04x, 0x%02x, 0x%02x, 0x%02x }",
            abbrevInfo[ u ].name,
            abbrevInfo[ u ].valid_mask, total,
            abbrevExtra[ u ].data_offset,
            abbrevExtra[ u ].data_len,
            abbrevInfo[ u ].tag
        );
        if( abbrevExtra[ u ].data_offset > 0xff ) {
            /* just change the uint_8 data_offset in the above structure */
            fprintf( stderr, "data_offset too large, must increase size of data_offset field\n" );
            exit( 1 );
        }
        if( abbrevExtra[ u ].data_len > 0xff ) {
            /* just change the uint_8 data_len in the above structure */
            fprintf( stderr, "data_len too large, must increase size of data_len field\n" );
            exit( 1 );
        }
        if( abbrevInfo[ u ].tag > 0xffff ) {
            /* just change the uint_16 tag in the above structure */
            fprintf( stderr, "Tag too large, must increase size of tag field\n" );
            exit( 1 );
        }
        total += 1 << CountBits( abbrevInfo[ u ].valid_mask & ~AB_ALWAYS );
        ++u;
        if( u == AB_MAX ) break;
        if( total > 0xffff ) {
            /* just change the uint_16 bit_index in the above structure */
            fprintf( stderr, "Index too large, must increase size of index field\n" );
            exit( 1 );
        }
        fprintf( fp, ",\n" );
    }
    fprintf( fp, "\n};\n" );
    return( total );
}


int main( void )
{

    FILE *                      fp;
    uint_32                     total;

    fp = fopen( "dwabinfo.gh", "w" );
    if( fp == NULL ) {
        fprintf( stderr, "unable to open dwabinfo.i for writing: %s",
            strerror( errno ) );
        return( 1 );
    }
    fprintf( fp, "/* this file created by dwmakeab.c */\n" );
    emitEncodings( fp );
    total = emitInfo( fp );
    fclose( fp );

    fp = fopen( "dwabenum.gh", "w" );
    if( fp == NULL ) {
        fprintf( stderr, "unable to open dwabenum.i for writing: %s",
            strerror( errno ) );
        return( 1 );
    }
    fprintf( fp, "/* this file created by dwmakeab.c */\n" );
    /* we need this value for determining the size of the dw_client struct */
    fprintf( fp, "\n#define AB_LAST_CODE    0x%08lx\n\n",  total );
    fprintf( fp, "\n#define AB_BITVECT_SIZE 0x%08lx\n\n", ( total + 7 ) / 8 );
    emitEnum( fp );
    fprintf( fp, "\n" );
    fclose( fp );

    return( 0 );
}

⌨️ 快捷键说明

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