📄 cdecl2.c
字号:
if( flags & info->modifier ){
CWarn1(WARN_REPEATED_MODIFIER, ERR_REPEATED_MODIFIER );
}
info->modifier |= flags;
if( CurToken == T___BASED ) {
bool use_seg;
use_seg = FALSE;
NextToken();
MustRecog( T_LEFT_PAREN );
info->based_kind = BASED_NONE;
if( CurToken == T_LEFT_PAREN ) {
NextToken();
MustRecog( T___SEGMENT );
MustRecog( T_RIGHT_PAREN );
use_seg = TRUE;
}
switch( CurToken ) {
case T_ID: /* __based(variable) */
sym_handle = SymLook( HashValue, Buffer );
if( sym_handle == 0 ) { /* 10-jan-92 */
SymCreate( &sym, Buffer );
sym.stg_class = SC_EXTERN; /* indicate extern decl */
CErr2p( ERR_UNDECLARED_SYM, Buffer );
sym.sym_type = GetType( TYPE_INT );
sym_handle = SymAdd( HashValue, &sym );
}else{
TYPEPTR typ;
SymGet( &sym, sym_handle );
typ = sym.sym_type;
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( use_seg ){
info->based_kind = BASED_VARSEG;
if( typ->decl_type != TYPE_POINTER ){
CErr1( ERR_SYM_MUST_BE_TYPE_SEGMENT );
info->based_kind = BASED_NONE;
}
}else if( typ->decl_type == TYPE_POINTER ){
info->based_kind = BASED_VAR;
}else if( (sym.attrib & FLAG_SEGMENT) ) {
info->based_kind = BASED_SEGVAR;
}else{
CErr1( ERR_SYM_MUST_BE_TYPE_SEGMENT );
info->based_kind = BASED_NONE;
}
}
if( ! (sym.flags & SYM_REFERENCED) ) { /* 10-jan-92 */
sym.flags |= SYM_REFERENCED;
SymReplace( &sym, sym_handle );
}
NextToken();
break;
case T_VOID: /* __based(void) */
if( use_seg ){
CErr1( ERR_INVALID_BASED_DECLARATOR );
}
info->based_kind = BASED_VOID;
NextToken();
break;
case T___SEGNAME: /* __based(__segname("string")) */
if( use_seg ){
CErr1( ERR_INVALID_BASED_DECLARATOR );
}
info->based_kind = BASED_SEGNAME;
NextToken();
MustRecog( T_LEFT_PAREN );
if( CurToken == T_STRING ) {
info->segment = AddSegName( Buffer, "", SEGTYPE_BASED);
sym_handle = SegSymHandle( info->segment );
SymGet( &sym, sym_handle );
sym.u.var.segment = info->segment;
SymReplace( &sym, sym_handle );
NextToken();
} else {
CErr1( ERR_SEGMENT_NAME_REQUIRED );
info->based_kind = BASED_NONE;
}
MustRecog( T_RIGHT_PAREN );
break;
case T___SELF: /* __based(__self) */
info->based_kind = BASED_SELFSEG;
NextToken();
break;
case T_AND: /* __based((__segment) &var ) */
if( !use_seg ){
CErr1( ERR_INVALID_BASED_DECLARATOR );
}
NextToken();
if( CurToken == T_ID ) {
sym_handle = SymLook( HashValue, Buffer );
if( sym_handle == 0 ) { /* 10-jan-92 */
SymCreate( &sym, Buffer );
sym.stg_class = SC_EXTERN; /* indicate extern decl */
CErr2p( ERR_UNDECLARED_SYM, Buffer );
sym.sym_type = GetType( TYPE_INT );
sym_handle = SymAdd( HashValue, &sym );
} else {
SymGet( &sym, sym_handle );
}
if( ! (sym.flags & SYM_REFERENCED) ) { /* 10-jan-92 */
sym.flags |= SYM_REFERENCED;
SymReplace( &sym, sym_handle );
}
info->based_kind = BASED_SEGNAME;
NextToken();
}else{
CErr1( ERR_INVALID_BASED_DECLARATOR );
}
break;
default:
CErr1( ERR_INVALID_BASED_DECLARATOR );
break;
}
MustRecog( T_RIGHT_PAREN );
info->modifier &= ~(FLAG_NEAR|FLAG_FAR|FLAG_HUGE);
info->modifier = FLAG_NEAR | FLAG_BASED;
}
if( CurToken == T_TIMES ) {
NextToken();
#if _MACHINE == _PC
// * seg16 binds with * cause of IBM dorks, and so does far16
if( CurToken == T__SEG16 || CurToken == T___FAR16 ) {
#if _CPU == 386 /* 15-nov-91 */
info->modifier |= FLAG_FAR16;
#else
info->modifier |= FLAG_FAR;
#endif
NextToken();
}
#endif
flags = info->modifier & ~FLAG_EXPORT;
ptr_typ = BPtrNode( ptr_typ, flags, info->segment,
sym_handle, info->based_kind );
sym_handle = 0;
info->segment = 0; // start over
info->modifier = TypeQualifier(); // .. * const
info->based_kind = BASED_NONE;
} else {
break;
}
}
return( ptr_typ );
}
local void ParseDeclPart2( TYPEPTR *typep, TYPEPTR typ )
{
TYPEPTR decl1;
TYPEPTR decl2;
type_modifiers mod = FLAG_NONE;
decl1 = *typep;
if( decl1 != NULL ) {
while( decl1->object != NULL ) {
decl1 = decl1->object;
}
}
// Pass on pointer flags
if( ( decl1 != NULL ) && ( decl1->decl_type == TYPE_POINTER ) )
mod = decl1->u.p.decl_flags;
decl2 = DeclPart2( typ, mod );
if( decl1 == NULL ) {
*typep = decl2;
} else {
decl1->object = decl2;
if( decl1->decl_type == TYPE_POINTER && decl2 != NULL ) {
AddPtrTypeHash( decl1 );
}
}
}
static void AbsDecl( SYMPTR sym, type_modifiers mod, TYPEPTR typ )
{
auto struct mod_info info;
info.segment = 0;
info.modifier = mod;
info.based_kind = BASED_NONE;
info.based_sym = 0;
typ = Pointer( typ, &info );
if( CurToken == T_LEFT_PAREN ) {
NextToken();
if( CurToken == T_RIGHT_PAREN ) {
typ = FuncNode( typ, info.modifier, NULL );
} else {
AbsDecl( sym, info.modifier, (TYPEPTR) NULL );
info.modifier = FLAG_NONE;
MustRecog( T_RIGHT_PAREN );
ParseDeclPart2( &sym->sym_type, typ );
}
} else {
sym->attrib = info.modifier;
sym->u.var.segment = info.segment; /* 01-dec-91 */
typ = DeclPart2( typ, info.modifier );
sym->sym_type = typ;
}
}
void Declarator( SYMPTR sym, type_modifiers mod, TYPEPTR typ, decl_state state )
{
TYPEPTR *type_list;
TYPEPTR parm_type;
auto struct mod_info info;
info.segment = 0;
info.modifier = mod;
info.based_kind = BASED_NONE;
info.based_sym = 0;
typ = Pointer( typ, &info );
if( CurToken == T_LEFT_PAREN ) {
NextToken();
if( state & DECL_STATE_ISPARM ) {
parm_type = TypeName(); /* 14-mar-91 */
} else {
parm_type = NULL;
}
if( parm_type != NULL || CurToken == T_RIGHT_PAREN ) {
type_list = NULL;
if( parm_type != NULL ) {
type_list = MakeParmList( NewParm(parm_type,NULL), 1, 0 );
}
typ = FuncNode( typ, info.modifier, type_list );
typ = PtrNode( typ, 0, SEG_DATA );
MustRecog( T_RIGHT_PAREN );
} else {
if( (state & DECL_STATE_ISPARM) && TokenClass[ CurToken ] == TC_STG_CLASS ) {
typ = DeclPart3( typ, info.modifier );
} else {
Declarator( sym, info.modifier, (TYPEPTR) NULL, state );
info.modifier = FLAG_NONE;
MustRecog( T_RIGHT_PAREN );
}
}
ParseDeclPart2( &sym->sym_type, typ );
typ = sym->sym_type;
// Transfer function attributes to type; TODO: figure out a better way
if( typ && typ->decl_type == TYPE_FUNCTION )
typ->type_flags = sym->attrib;
} else {
if( CurToken == T_ID || CurToken == T_SAVED_ID ) {
for(;;) {
if( CurToken == T_ID ) {
SymCreate( sym, Buffer );
sym->info.hash_value = HashValue;
NextToken();
} else {
SymCreate( sym, SavedId );
sym->info.hash_value = SavedHash;
CurToken = LAToken;
}
if( CurToken != T_ID && CurToken != T_TIMES ) break;
if( state & DECL_STATE_NOTYPE ) {
CErr2p( ERR_MISSING_DATA_TYPE, sym->name );
if( CurToken == T_TIMES ) { /* "garbage *p" */
typ = Pointer( typ, &info );
}
} else if( CurToken == T_TIMES ) {
Expecting( "," );
} else {
Expecting( ",' or ';" );
}
if( CurToken != T_ID ) break;
CMemFree( sym->name );
}
} else {
SymCreate( sym, "" );
}
sym->attrib = info.modifier;
sym->u.var.segment = info.segment; /* 01-dec-91 */
#if 0
if( modifier & FLAG_INTERRUPT ) sym->flags |= SYM_INTERRUPT_FN;
#endif
typ = DeclPart2( typ, info.modifier );
sym->sym_type = typ;
}
if( typ != NULL ) {
if( typ->decl_type == TYPE_FUNCTION ) { /* 07-jun-94 */
if( info.segment != 0 ) { // __based( __segname("X"))
SetFuncSegment( sym, info.segment );
}
}
}
}
FIELDPTR FieldCreate( char *name )
{
FIELDPTR field;
field = (FIELDPTR) CPermAlloc( sizeof(FIELD_ENTRY) + strlen( name ) );
strcpy( field->name, name );
if( CompFlags.emit_browser_info ) { /* 27-oct-94 */
field->xref = NewXref( NULL );
}
return( field );
}
FIELDPTR FieldDecl( TYPEPTR typ, type_modifiers mod, decl_state state )
{
FIELDPTR field;
auto struct mod_info info;
info.segment = 0;
info.modifier = mod;
info.based_kind = BASED_NONE;
info.based_sym = 0;
typ = Pointer( typ, &info );
if( CurToken == T_LEFT_PAREN ) {
NextToken();
field = FieldDecl( (TYPEPTR) NULL, info.modifier, DECL_STATE_NONE );
info.modifier = FLAG_NONE;
MustRecog( T_RIGHT_PAREN );
ParseDeclPart2( &field->field_type, typ );
} else {
if( CurToken == T_ID ) {
for(;;) {
field = FieldCreate( Buffer );
NextToken();
if( CurToken != T_ID && CurToken != T_TIMES ) break;
if( state & DECL_STATE_NOTYPE ) {
CErr2p( ERR_MISSING_DATA_TYPE, field->name );
if( CurToken == T_TIMES ) { /* "garbage *p" */
typ = Pointer( typ, &info );
}
} else if( CurToken == T_TIMES ) {
Expecting( "," );
} else {
Expecting( ",' or ';" );
}
if( CurToken != T_ID ) break;
}
} else {
field = FieldCreate( "" );
}
field->attrib = info.modifier;
typ = DeclPart2( typ, info.modifier );
field->field_type = typ;
}
return( field );
}
local TYPEPTR ArrayDecl( TYPEPTR typ )
{
long dimension;
TYPEPTR first_node, next_node, prev_node;
if( typ != NULL ) { /* 16-mar-90 */
if( typ->decl_type == TYPE_FUNCTION ) {
CErr1( ERR_CANT_HAVE_AN_ARRAY_OF_FUNCTIONS );
}
}
first_node = NULL;
prev_node = NULL;
while( CurToken == T_LEFT_BRACKET ) {
NextToken();
if( CurToken != T_RIGHT_BRACKET ) {
const_val val;
if( ConstExprAndType( &val ) ){
dimension = val.val32;
}else{
dimension = 1;
}
if( dimension <= 0 ) {
CErr1( ERR_INVALID_DIMENSION );
dimension = 1;
}
} else {
if( first_node == NULL ) {
dimension = 0;
} else {
CErr1( ERR_DIMENSION_REQUIRED );
dimension = 1;
}
}
MustRecog( T_RIGHT_BRACKET );
next_node = ArrayNode( typ );
next_node->u.array->dimension = dimension;
if( first_node == NULL ) {
first_node = next_node;
} else {
prev_node->object = next_node;
}
prev_node = next_node;
}
return( first_node );
}
static TYPEPTR DeclPart3( TYPEPTR typ, type_modifiers mod )
{
PARMPTR parm_list;
TYPEPTR *parms;
local TYPEPTR *FuncProtoType();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -