⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdecl2.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        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 + -