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 + -
显示快捷键?