static BASETYPE get_basetype( VARSPACE * v ) { TYPEDEF t ; BASETYPE type = TYPE_UNDEFINED, newtype ; int n ; for ( n = 0 ; n < v->count ; n++ ) { t = v->vars[n].type ; while ( typedef_is_array( t ) ) { t = typedef_reduce( t ) ; } if ( typedef_is_struct( t ) ) { newtype = get_basetype( typedef_members( t ) ) ; } else { newtype = typedef_base( t ) ; } if ( type != TYPE_UNDEFINED && type != newtype ) { return TYPE_UNDEFINED ; } type = newtype ; } return type ; }
void varspace_dump( VARSPACE * n, int indent ) { int i, t, to ; char buffer[128] ; for ( i = 0 ; i < n->count ; i++ ) { if ( i < n->count - 1 ) to = n->vars[i+1].offset - 1 ; else to = n->last_offset - 1 ; printf( "[%04d:%04d]\t", n->vars[i].offset, to ) ; for ( t = 0 ; t < indent ; t++ ) printf( " + " ) ; typedef_describe( buffer, n->vars[i].type ) ; printf( "%s %s", buffer, identifier_name( n->vars[i].code ) ) ; /* Describe arrays of structs */ if ( typedef_is_array( n->vars[i].type ) ) { TYPEDEF r = typedef_reduce( n->vars[i].type ); while ( typedef_is_array( r ) ) r = typedef_reduce( r ); if ( typedef_is_struct( r ) ) { printf( ":\n" ) ; varspace_dump( typedef_members( r ), indent + 1 ) ; } else printf( "\n" ); } /* Describe structs */ else if ( typedef_is_struct( n->vars[i].type ) ) { printf( ":\n" ) ; varspace_dump( typedef_members( n->vars[i].type ), indent + 1 ) ; } else printf( "\n" ) ; } }
int compile_struct_data( VARSPACE * n, segment * data, int size, int sub ) { int elements = 0 ; int position = 0 ; expresion_result res ; for ( ;; ) { token_next() ; /* Allow parenthized struct initialization */ if ( token.type == IDENTIFIER && token.code == identifier_leftp ) { if (( elements % n->count ) != 0 ) compile_error( MSG_NOT_ENOUGH_INIT ); /* Note - don't ignore a trailing comma! */ elements = compile_struct_data( n, data, size, 0 ) ; if ( elements >= n->count ) size -= ( elements / n->count ); token_next() ; if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ) ; token_next() ; if (( elements % n->count ) == 0 && size > 0 && token.type == IDENTIFIER && token.code == identifier_comma ) continue; token_back() ; return elements ; } /* Allow empty initialization */ if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) return 0 ; token_back() ; for ( ;; ) { TYPEDEF next_type = n->vars[position].type ; /* Next variable is a pointer */ if ( typedef_is_pointer( next_type ) ) { res = compile_expresion( 1, 0, 0, TYPE_DWORD ) ; if ( !res.constant ) compile_error( MSG_INCORRECT_PTR_INIT ); segment_add_as( data, 0, TYPE_POINTER ) ; } else if ( typedef_is_array( next_type ) ) /* Next variable is an array */ { int elements = typedef_tcount( next_type ) ; BASETYPE base; /* Get the array base type */ while ( typedef_is_array( next_type ) ) next_type = typedef_reduce( next_type ); base = typedef_base( next_type ); /* Special case: array of structs */ if ( base == TYPE_STRUCT ) { compile_struct_data( next_type.varspace, data, elements, 1 ); } else { token_next(); /* Special case: intializing char[] strings */ if ( token.type == STRING && next_type.chunk[1].type == TYPE_CHAR ) { const char * str = string_get( token.code ) ; int subcount = 0 ; if (( int )strlen( str ) > typedef_count( next_type ) - 1 ) compile_error( MSG_TOO_MANY_INIT ) ; while ( *str ) { segment_add_as( data, *str++, TYPE_CHAR ) ; subcount++ ; } while ( subcount++ < typedef_count( next_type ) ) segment_add_as( data, 0, TYPE_CHAR ) ; } else /* Initializing normal arrays */ { int has_parents = 1; if ( token.type != IDENTIFIER || token.code != identifier_leftp ) { has_parents = 0; token_back(); } compile_array_data( n, data, elements, elements, &base ) ; if ( has_parents ) { token_next() ; if ( token.type != IDENTIFIER || token.code != identifier_rightp ) compile_error( MSG_EXPECTED, ")" ) ; } } } } else if ( typedef_is_struct( next_type ) ) /* Next variable is another struct */ { compile_struct_data( next_type.varspace, data, 1, 1 ) ; } else /* Next variable is a single type */ { res = compile_expresion( 1, 0, 0, typedef_base( next_type ) ) ; if ( !res.constant ) compile_error( MSG_CONSTANT_EXP ); segment_add_as( data, typedef_base( next_type ) == TYPE_FLOAT ? *( int* )&res.fvalue : res.value, typedef_base( next_type ) ) ; } position++ ; elements++ ; if ( position == n->count && size < 2 && sub ) break ; /* A comma should be here */ token_next() ; if ( token.type == IDENTIFIER && token.code == identifier_semicolon ) { token_back(); break ; } if ( token.type == IDENTIFIER && token.code == identifier_rightp ) { token_back() ; break ; } if ( token.type != IDENTIFIER || token.code != identifier_comma ) compile_error( MSG_EXPECTED, "," ) ; /* Wrap around for the next struct */ if ( position == n->count ) { if ( size == 1 && !sub ) compile_error( MSG_TOO_MANY_INIT ) ; size--; position = 0; } } break; } return elements ; }
void typedef_describe( char * buffer, TYPEDEF t ) { switch ( t.chunk[0].type ) { case TYPE_INT: sprintf( buffer, "INT" ) ; return ; case TYPE_DWORD: sprintf( buffer, "DWORD" ) ; return ; case TYPE_SHORT: sprintf( buffer, "SHORT" ) ; return ; case TYPE_WORD: sprintf( buffer, "WORD" ) ; return ; case TYPE_BYTE: sprintf( buffer, "BYTE" ) ; return ; case TYPE_CHAR: sprintf( buffer, "CHAR" ) ; return ; case TYPE_SBYTE: sprintf( buffer, "SIGNED BYTE" ) ; return ; case TYPE_STRING: sprintf( buffer, "STRING" ) ; return ; case TYPE_FLOAT: sprintf( buffer, "FLOAT" ) ; return ; case TYPE_STRUCT: if ( t.chunk[0].count > 1 ) sprintf( buffer, "STRUCT [%d]", t.chunk[0].count ) ; else sprintf( buffer, "STRUCT" ) ; return ; case TYPE_ARRAY: sprintf( buffer, "ARRAY [%d] OF ", t.chunk[0].count ) ; typedef_describe( buffer + strlen( buffer ), typedef_reduce( t ) ) ; return ; case TYPE_POINTER: sprintf( buffer, "POINTER TO " ) ; typedef_describe( buffer + strlen( buffer ), typedef_reduce( t ) ) ; return ; case TYPE_UNDEFINED: default: sprintf( buffer, "<UNDEFINED>" ) ; return ; } }