📄 cdecl2.c
字号:
switch( sym->declspec ){
case DECLSPEC_DLLIMPORT:
case DECLSPEC_THREAD:
CErr2p( ERR_MODIFIERS_DISAGREE, sym->name );
break;
case DECLSPEC_DLLEXPORT:
if( old_sym.declspec == DECLSPEC_DLLIMPORT ){
old_sym.declspec = DECLSPEC_DLLEXPORT;
}else{
CErr2p( ERR_MODIFIERS_DISAGREE, sym->name );
}
break;
}
}
}
SetDiagPop();
}
if( ( old_sym_handle != 0 ) &&
( stg_class == SC_NULL || stg_class == SC_EXTERN ||
(stg_class == SC_STATIC && SymLevel == 0 ) ) ) {
/* make sure sym->sym_type same type as old_sym->sym_type */
SetDiagSymbol( &old_sym, old_sym_handle );
which = VerifyType( sym->sym_type, old_sym.sym_type, sym );
SetDiagPop();
if( which == 0 && old_sym.level == SymLevel ) { /* 06-jul-88 AFS */
/* new symbol's type supersedes old type */
old_sym.sym_type = sym->sym_type;
if( (old_sym.flags & SYM_FUNCTION) ) {
old_sym = *sym; // ditch old sym
}
SymReplace( &old_sym, old_sym_handle );
}
if( stg_class == SC_EXTERN && SymLevel != 0 ) goto new_var;
CMemFree( sym->name );
memcpy( sym, &old_sym, sizeof( SYM_ENTRY ) );
sym_handle = old_sym_handle;
if( stg_class == SC_NULL || stg_class == SC_STATIC ) {
if( sym->stg_class == SC_EXTERN ) {
sym->stg_class = /*SC_NULL*/ stg_class; /* 03-oct-88 */
} else if( sym->stg_class == SC_STATIC ) {
if( stg_class == SC_NULL ) {
CErrSymName( ERR_STG_CLASS_DISAGREES, sym, sym_handle );
}
}
}
} else {
if( stg_class == SC_EXTERN && SymLevel != 0 ) {
; /* do nothing 29-jan-93 */
} else {
VfyNewSym( sym->info.hash_value, sym->name );
}
new_var:
old_sym_handle = 0;
sym->flags |= SYM_DEFINED;
typ = SkipDummyTypedef( sym->sym_type ); /* 25-nov-94 */
if( typ->decl_type == TYPE_TYPEDEF ) { /* 12-mar-92 */
SymGet( &sym2, typ->u.typedefn );
if( sym->u.var.segment == 0 && sym2.u.var.segment != 0 ) {
sym->u.var.segment = sym2.u.var.segment;
}
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
}
if( typ->decl_type == TYPE_VOID ) {
CErr2p( ERR_VAR_CANT_BE_VOID, sym->name );
sym->sym_type = TypeDefault();
}
sym->stg_class = stg_class;
sym_handle = SymAdd( sym->info.hash_value, sym );
}
if( sym->u.var.segment == 0 && /* 22-oct-92 */
(stg_class == SC_STATIC ||
stg_class == SC_NULL ||
stg_class == SC_EXTERN) ) {
if( DefDataSegment != 0 ) {
sym->u.var.segment = DefDataSegment;
SymReplace( sym, sym_handle );
}
}
if( CurToken == T_EQUAL ) {
if( stg_class == SC_EXTERN ) {
stg_class = SC_STATIC;
if( SymLevel == 0 ) {
CompFlags.external_defn_found = 1;
stg_class = SC_NULL;
} else {
CErr1( ERR_CANT_INITIALIZE_EXTERN_VAR );
}
}
sym->stg_class = stg_class;
NextToken();
VarDeclEquals( sym, sym_handle );
sym->flags |= SYM_ASSIGNED;
}
SymReplace( sym, sym_handle ); /* 06-jul-88 */
if( old_sym_handle != 0 ) sym_handle = 0;
return( sym_handle );
}
static SYM_HANDLE InitDeclarator( SYMPTR sym,
decl_info const * const info,
decl_state *state )
{
SYM_HANDLE sym_handle;
SYM_HANDLE old_sym_handle;
type_modifiers flags;
TYPEPTR typ;
TYPEPTR otyp;
auto SYM_ENTRY old_sym;
if( ParmList != NULL ) {
FreeParmList();
}
memset( sym, 0, sizeof( SYM_ENTRY ) ); /* 02-apr-91 */
sym->name = "";
flags = TypeQualifier(); /* 08-nov-94 */
if( flags & info->mod ){
CErr1( ERR_INV_TYPE );
}
flags |= info->mod;
if( info->decl == DECLSPEC_DLLEXPORT ){
flags |= FLAG_EXPORT; //need to get rid of this
}
Declarator( sym, flags, info->typ, *state );
if( sym->name[0] == '\0' ) {
InvDecl();
return( 0 );
}
typ = sym->sym_type;
/* skip over typedef's 29-aug-89 */
while( typ->decl_type == TYPE_TYPEDEF ) typ = typ->object;
if( info->stg == SC_TYPEDEF ) {
if( CompFlags.extensions_enabled ) { /* 24-mar-91 */
old_sym_handle = SymLook( sym->info.hash_value, sym->name );
if( old_sym_handle != 0 ) {
SymGet( &old_sym, old_sym_handle );
otyp = old_sym.sym_type; /* skip typedefs 25-sep-92 */
while( otyp->decl_type == TYPE_TYPEDEF ) otyp = otyp->object;
if( old_sym.stg_class == SC_TYPEDEF &&
old_sym.level == SymLevel &&
IdenticalType( typ, otyp ) ) {
return( 0 ); /* indicate already in symbol tab */
}
}
}
VfyNewSym( sym->info.hash_value, sym->name );
sym->stg_class = info->stg;
sym_handle = SymAdd( sym->info.hash_value, sym );
} else {
sym->declspec = info->decl;
sym->naked = info->naked;
if( sym->declspec == DECLSPEC_DLLEXPORT ){ //sync up flags
sym->attrib |= FLAG_EXPORT; //need to get rid of this
}else if( sym->attrib & FLAG_EXPORT ){
if( sym->declspec == DECLSPEC_NONE ){
sym->declspec = DECLSPEC_DLLEXPORT;
}else if( sym->declspec != DECLSPEC_DLLEXPORT ){
CErr1( ERR_INVALID_DECLSPEC );
}
}
if( typ->decl_type == TYPE_FUNCTION ) {
sym_handle = FuncDecl( sym, info->stg, state );
} else {
sym_handle = VarDecl( sym, info->stg, state );
}
}
return( sym_handle );
}
int DeclList( SYM_HANDLE *sym_head )
{
decl_state state;
SYM_HANDLE sym_handle;
SYM_HANDLE prevsym_handle;
unsigned line_num;
auto SYM_ENTRY sym;
auto SYM_ENTRY prevsym;
decl_info info;
ParmList = NULL;
prevsym_handle = 0;
*sym_head = 0;
for(;;) {
for(;;) {
for(;;) {
while( CurToken == T_SEMI_COLON ) {
if( SymLevel == 0 ) {
if( !CompFlags.extensions_enabled ) { /* 28-nov-94 */
CErr2p( ERR_EXPECTING_DECL_BUT_FOUND, ";" );
}
}
NextToken();
}
if( CurToken == T_EOF ) return( 0 );
line_num = TokenLine;
FullDeclSpecifier( &info );
if( info.stg != SC_NULL || info.typ != NULL ) break;
if( SymLevel != 0 ) return( 0 );
break;
}
state = DECL_STATE_NONE;
if( info.typ == NULL ) {
state |= DECL_STATE_NOTYPE;
info.typ = TypeDefault();
}
if( info.stg == SC_NULL && (state & DECL_STATE_NOTYPE) ) {
switch( CurToken ) {
case T_ID:
case T_LEFT_PAREN:
case T___EXPORT:
case T___LOADDS:
case T___NEAR:
case T___FAR:
case T___HUGE:
case T___CDECL:
case T___PASCAL:
case T___FORTRAN:
case T__SYSCALL: /* 04-jul-91 */
case T___STDCALL: /* 03-feb-95 */
case T___FASTCALL:
case T___INTERRUPT:
case T___SAVEREGS:
case T_TIMES: /* 30-nov-94 */
break;
case T_IF:
case T_FOR:
case T_WHILE:
case T_DO:
case T_SWITCH:
case T_BREAK:
case T_CONTINUE:
case T_CASE:
case T_DEFAULT:
case T_ELSE:
case T_GOTO:
case T_RETURN:
FlushBadCode();
continue;
default:
CErr2p( ERR_EXPECTING_DECL_BUT_FOUND, Tokens[CurToken] );
NextToken();
break;
}
}
break;
}
if( CurToken != T_SEMI_COLON ) {
if( info.decl == DECLSPEC_DLLIMPORT ) {
if(!CompFlags.rent ){
if( info.stg == SC_NULL ) info.stg = SC_EXTERN;
}
}
for( ;; ) {
sym_handle = InitDeclarator( &sym, &info, &state );
/* NULL is returned if sym already exists in symbol table */
if( sym_handle != 0 ) {
sym.handle = 0;
if( (sym.flags & SYM_FUNCTION) ) {
if( !(state & DECL_STATE_NOTYPE ) ) {
sym.flags |= SYM_TYPE_GIVEN;
}
} else if( SymLevel > 0 ) { /* variable */
if( prevsym_handle != 0 ) {
SymGet( &prevsym, prevsym_handle );
prevsym.handle = sym_handle;
SymReplace( &prevsym, prevsym_handle );
}
if( *sym_head == 0 ) {
*sym_head = sym_handle;
}
prevsym_handle = sym_handle;
}
SymReplace( &sym, sym_handle );
}
/* case "int x *p" ==> missing ',' msg already given */
if( CurToken != T_TIMES ) {
if( CurToken != T_COMMA ) break;
NextToken();
}
}
/* the following is illegal:
typedef double math(double);
math sin { ; }
That's the reason for the check
"typ->decl_type != TYPE_FUNCTION"
*/
if( SymLevel == 0 && CurToken != T_SEMI_COLON
&& sym_handle != 0 ) {
if( sym.sym_type->decl_type == TYPE_FUNCTION
&& sym.sym_type != info.typ ) { /* 21-mar-89 */
CurFuncHandle = sym_handle;
CurFunc = &CurFuncSym;
memcpy( CurFunc, &sym, sizeof( SYM_ENTRY ) );
return( 1 ); /* indicate this is a function defn */
}
}
MustRecog( T_SEMI_COLON );
} else {
Chk_Struct_Union_Enum( info.typ );
NextToken(); /* skip over ';' */
}
}
// can't get here! return( 0 );
}
TYPEPTR TypeName()
{
TYPEPTR typ;
decl_info info;
SYM_ENTRY abs_sym;
TypeSpecifier( &info );
typ = info.typ;
if( typ != NULL ) {
memset( &abs_sym, 0, sizeof( SYM_ENTRY ) );
abs_sym.name = "";
AbsDecl( &abs_sym, info.mod, info.typ );
typ = abs_sym.sym_type;
}
return( typ );
}
local type_modifiers GetModifiers( void )
{
type_modifiers modifier;
int hash;
static type_modifiers const ModifierFlags[] = {
0,
FLAG_NEAR, // TC_NEAR
FLAG_FAR, // TC_FAR
#if _CPU == 8086
FLAG_HUGE, // TC_HUGE
#else
FLAG_FAR, // TC_HUGE // close
#endif
#if _CPU == 8086
FLAG_FAR, // TC_FAR16 // avoid giving error
#else
FLAG_FAR16, // TC_FAR16
#endif
FLAG_INTERRUPT, // TC_INTERRUPT
LANG_CDECL, // TC_CDECL
LANG_PASCAL, // TC_PASCAL
LANG_FORTRAN, // TC_FORTRAN
LANG_SYSCALL, // TC_SYSCALL /* 04-jul-91 */
LANG_STDCALL, // TC_STDCALL
LANG_FASTCALL, // TC_FASTCALL
LANG_OPTLINK, // TC_OPTLINK
FLAG_EXPORT, // TC_EXPORT
FLAG_LOADDS, // TC_LOADDS
FLAG_SAVEREGS, // TC_SAVEREGS
};
modifier = 0;
for(;;) {
hash = TokenClass[ CurToken ];
if( hash >= TC_MODIFIER ) break; /* 04-jul-90, c/=/>=/ */
modifier |= ModifierFlags[ hash ];
NextToken();
}
return( modifier );
}
struct mod_info {
int segment;
type_modifiers modifier; // const, vol flags
BASED_KIND based_kind;
SYM_HANDLE based_sym;
};
local TYPEPTR Pointer( TYPEPTR ptr_typ, struct mod_info *info )
{
type_modifiers flags;
SYM_HANDLE sym_handle;
auto SYM_ENTRY sym;
sym_handle = 0;
if( ptr_typ != NULL && ptr_typ->decl_type == TYPE_TYPEDEF ) {
// get segment from typedef TODO should be done sooner
TYPEPTR typ;
SYMPTR symp;
typ = SkipDummyTypedef( ptr_typ ); /* 25-nov-94 */
if( typ->decl_type == TYPE_TYPEDEF ) { /* 15-mar-92 */
symp = SymGetPtr( typ->u.typedefn );
if( info->modifier & FLAG_BASED ) {
info->segment = symp->u.var.segment;
sym_handle = SegSymHandle( info->segment );
}
}
}
for(;;) {
flags = GetModifiers(); // NEAR FAR CDECL stuff
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -