cdecl1.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 573 行 · 第 1/2 页

C
573
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Parse functions, prototypes, handle argument promotion.
*
****************************************************************************/


#include "cvars.h"
#include "cgswitch.h"
#include "langenv.h"

extern  struct  parm_list   *NewParm( TYPEPTR, struct parm_list * );

extern  TREEPTR     CurFuncNode;

        TYPEPTR *MakeParmList( struct parm_list *, int, int );
local   void    ParmDeclList( void );
local   void    AddParms( void );
local   void    ChkParms( void );
local   void    FuncDefn( SYMPTR );

local   void    BeginFunc( void );
local   void    ReverseParms( void );       /* reverse order of parms */


void ParsePgm( void )
{
    SYM_HANDLE      dummysym;

    CompFlags.external_defn_found = 0;
    CompFlags.initializing_data   = 0;
    dummysym = 0;
    GlobalSym = 0;

    do {
        if( DeclList( &dummysym ) ) {  /* if this is a function defn */
            FuncDefn( CurFunc );
            SrcLineNum = CurFunc->d.defn_line;  /* 17-aug-88 */
            SrcFno     = CurFunc->defn_file_index;
            GenFunctionNode( CurFuncHandle );

            SymLevel = 1;
            ParmDeclList();
            SymLevel = 0;
            if( CurToken == T_LEFT_BRACE ) {
                BeginFunc();
                Statement();
                CMemFree( CurFunc->name );
                CurFunc->name = NULL;
                SymReplace( CurFunc, CurFuncHandle );
                CurFunc = NULL;
                CurFuncNode = NULL;
                CurFuncHandle = 0;
            } else {
                MustRecog( T_LEFT_BRACE );
            }
        }
    } while( CurToken != T_EOF );

    if( CompFlags.external_defn_found == 0 ) {
        if( !CompFlags.extensions_enabled ) {       /* 20-mar-90 */
            CErr1( ERR_NO_EXTERNAL_DEFNS_FOUND );
        }
    }
}


local void FuncDefn( SYMPTR sym )
{
    SYM_NAMEPTR sym_name;
    int         sym_len;
    TYPEPTR     typ;

    /* duplicate name in near space */
    sym_name = SymName( sym, CurFuncHandle );
    sym_len = far_strlen_plus1( sym_name );
    sym->name = CMemAlloc( sym_len );
    far_memcpy( sym->name, sym_name, sym_len );
    if( sym->flags & SYM_DEFINED ) {
        CErr2p( ERR_SYM_ALREADY_DEFINED, sym->name );   /* 03-aug-88 */
    }
    typ = sym->sym_type->object;                /* get return type */
    SKIP_TYPEDEFS( typ );

    if( typ->decl_type != TYPE_VOID ) {         /* 26-mar-91 */
        if( TypeSize( typ ) == 0 ) {
            CErr( ERR_INCOMPLETE_TYPE, sym_name );
        }
    }
    sym->flags |= /*SYM_REFERENCED | 18-jan-89 */ SYM_DEFINED;

    if( !(GenSwitches & NO_OPTIMIZATION) ) {
        sym->flags |= SYM_OK_TO_RECURSE;                /* 25-sep-91 */
    }

    if( sym->stg_class == SC_EXTERN  ||  sym->stg_class == SC_FORWARD ) {
        sym->stg_class = SC_NULL;       /* indicate exported function */
    }

    CompFlags.external_defn_found = 1;
    if( Toggles & TOGGLE_CHECK_STACK )
        sym->flags |= SYM_CHECK_STACK;

    if( !CompFlags.zu_switch_used ) {
        if( (sym->attrib & FLAG_INTERRUPT) == FLAG_INTERRUPT ) {
            /* interrupt function */
            TargetSwitches |= FLOATING_SS;      /* force -zu switch on */
        } else {
            TargetSwitches &= ~FLOATING_SS;     /* turn it back off */
        }
    }
    if( strcmp( CurFunc->name, "main" ) == 0 || strcmp( CurFunc->name, "wmain" ) == 0 ) {
        sym->attrib &= ~FLAG_LANGUAGES;  // Turn off any language flags
        sym->attrib |= LANG_WATCALL;     // Turn on __watcall calling convention for main
    }
    SymReplace( sym, CurFuncHandle );
}


enum main_names {
    MAIN_WMAIN,
    MAIN_MAIN,
    MAIN_WWINMAIN,
    MAIN_WINMAIN,
    MAIN_WLIBMAIN,
    MAIN_LIBMAIN,
    MAIN_WDLLMAIN,
    MAIN_DLLMAIN,
    MAIN_NUM,
};

static char const   *MainNames[MAIN_NUM] = {
    "wmain",          // MAIN_WMAIN,
    "main",           // MAIN_MAIN,
    "wWinMain",       // MAIN_WWINMAIN,
    "WinMain",        // MAIN_WINMAIN,
    "wLibMain",       // MAIN_WLIBMAIN,
    "LibMain",        // MAIN_LIBMAIN,
    "wDllMain",       // MAIN_WDLLMAIN,
    "DllMain",        // MAIN_DLLMAIN,
};


local void BeginFunc( void )
{
    char                *name;
    char                *segname;
    enum main_names     main_entry;

    if( CurFunc->seginfo == NULL ) {                /* 18-nov-92 */
        CurFunc->seginfo = DefCodeSegment;          /* 22-oct-92 */
        if( CurFunc->seginfo == NULL ) {            /* 08-dec-92 */
            if( CompFlags.zm_switch_used ) {
                name = "";                          /* 05-feb-93 */
                if( TargetSwitches & BIG_CODE )
                    name = CurFunc->name;
                segname = TS_SEG_CODE; /* "_TEXT" */
                if( TextSegName[0] != '\0' ) {
                    segname = TextSegName;
                }
                CurFunc->seginfo = NewTextSeg( name, segname, "" );
            }
        }
    }
    name = CurFunc->name;
    for( main_entry = MAIN_WMAIN; main_entry < MAIN_NUM; ++main_entry ) {
       if( strcmp( name, MainNames[main_entry] ) == 0 ) {
           break;
       }
    }

    switch( main_entry ) {
    case MAIN_WMAIN:
        CompFlags.has_wchar_entry =1;
        // fall through!
    case MAIN_MAIN:
        if( CurFunc->u.func.parms ) {               /* 07-dec-88 */
            CompFlags.main_has_parms = 1;
        } else {
            CompFlags.main_has_parms = 0;
        }
        CompFlags.has_main = 1;
        break;

    case MAIN_WWINMAIN:
        CompFlags.has_wchar_entry =1;
        // fall through!
    case MAIN_WINMAIN:
        if( TargSys == TS_WINDOWS || TargSys == TS_CHEAP_WINDOWS
            || TargSys == TS_NT )
        {
            CompFlags.has_winmain = 1;
        } else {
            CompFlags.has_wchar_entry =0;
        }
        break;

    case MAIN_WLIBMAIN:
    case MAIN_WDLLMAIN:
        CompFlags.has_wchar_entry =1;
        // fall through!
    case MAIN_LIBMAIN:
    case MAIN_DLLMAIN:
        CompFlags.has_libmain = 1;
        break;

    case MAIN_NUM:
        break;
    }
}


static void  ArgPromotion( SYMPTR sym )
{
    TYPEPTR     typ;
    TYPEPTR     arg_typ;

    AdjParmType( sym );
    arg_typ = sym->sym_type;
    /* perform default argument promotions */
    typ = arg_typ;
    SKIP_TYPEDEFS( typ );

    switch( typ->decl_type ) {
#if 0
    case TYPE_CHAR:
    case TYPE_UCHAR:
    case TYPE_SHORT:
#endif
    case TYPE_ENUM:
        arg_typ = GetType( TYPE_INT );
        break;

#if 0
    case TYPE_USHORT:
        arg_typ = GetType( TYPE_UINT );
        break;

    case TYPE_FLOAT:
        arg_typ = GetType( TYPE_DOUBLE );
        break;
#endif
    default:
        break;
    }
}


local void ParmDeclList( void )     /* process old style function definitions */
{
    TYPEPTR             typ;
    PARMPTR             parm;
    decl_state          state;
    SYM_ENTRY           sym;
    decl_info           info;

    while( CurToken != T_LEFT_BRACE ) {
        FullDeclSpecifier( &info );
        if( info.stg == SC_NULL  &&  info.typ == NULL ) {
            if( CurToken == T_ID ) {
                CErr2p( ERR_MISSING_DATA_TYPE, Buffer );
            }
        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?