srusuprt.c

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

C
1,058
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include <stdarg.h>
#include <assert.h>
#include "global.h"
#include "hashtab.h"
#include "srusuprt.h"
#include "sruinter.h"
#include "ytab.gh"
#include "mem.h"
#include "keywords.h"
#include "lexxer.h"
#include "gen_cpp.h"
#include "options.h"
#include "error.h"
#include "list.h"
#include "filelist.h"

static sru_file         SRU;
static BOOL             inSubPgm;
static BOOL             setHeader;

#define PROTO_PRIME     257
#define OVERHEAD        16

/* required strings */
#define SRU_HEADER              "PBExportHeader$"
#define THIS_VARIABLE           "this_hdl"
#define THIS_TYPE               "ulong"
#define DECL_THIS_VAR           THIS_TYPE" "THIS_VARIABLE
#define LEFT_PAREN              "( "
#define RIGHT_PAREN             " )"
#define COMMA_DELIM             ", "
#define RETURN_STATEMENT        "return "
#define VARIABLE_SECTION        "type variables\n"
#define END_VARIABLE_SECTION    "end variables\n\n"
#define TYPE_PROTOTYPE_SECTION  "type prototypes\n"
#define END_PROTOTYPE_SECTION   "end prototypes\n\n"
#define FUNCTION                "function "
#define SUBROUTINE              "subroutine "
#define LIBRARY                 "library "
#define DLL_SUFFIX              ".dll"
#define NONAME_FILE             "noname"
#define REF_MODIFIER            "ref "
#define DQUOTE                  "\""
#define CONSTRUCTOR_EVENT       "constructor"
#define DESTRUCTOR_EVENT        "destructor"
#define ON_CONSTRUCTOR          "\non constructor\n"
#define ON_DESTRUCTOR           "on destructor\n"
#define END_ON                  "end on\n\n"
#define DES_CALL_TEMPLATE       "%s( this_hdl )\n"
#define CONS_CALL_TEMPLATE      "this_hdl = %s( )\n"
#define DES_DECL_TEMPLATE       "subroutine %s( ulong this_hdl ) library \"%s.dll\"\n"
#define CONS_DECL_TEMPLATE      "function ulong %s( ) library \"%s.dll\"\n"

static statement *replaceStatement( statement *locale, char *stmt );
static statement *insertStatement( statement *locale, char *stmt );
static statement *appendStatement( char *stmt );
static void freeStatement( statement *curr );

void yyerror( char *msg ) {
/*************************/

    msg = msg;
    GetToEOS();
}


static id_type isTypeKnown( TypeInfo *typ ) {
/********************************************/

/* checks hash table to determine if a type is known and if it is, returns it id
*/

    long        len;
    id_type     rc;
    keyword     *tmp;

    assert( typ );

    len = strlen( typ->name );
    tmp = FindHashEntry( SRU.typ_tab, HashString( typ->name, len ),
                         typ->name, len );
    if( tmp ) {
        rc = tmp->id;
        if( typ->isref ) {
            rc |= TY_REF_INDICATOR;
        }
        return( rc );
    }
    return( 0 );
}


static BOOL isConsDes( const char *name ) {
/*****************************************/

    assert( name );

    return( !stricmp( name, SRU.con_name ) || !stricmp( name, SRU.des_name ) );
}

void GetConstructor( char *uoname, char *buf ) {
/***********************************************/
    GenerateCoverFnName( uoname, "_CPP_CONSTRUCTOR", buf );
}

void GetDestructor( char *uoname, char *buf ) {
/**********************************************/
    GenerateCoverFnName( uoname, "_CPP_DESTRUCTOR", buf );
}

static void mkConsDesNames( void ) {
/**********************************/

/* puts together SRU constructor and destructor names */

    int         len;
    char        *classname;

    classname = GetClass();
    assert( classname );

    if( SRU.con_name ) {
        MemFree( SRU.con_name );
    }
    if( SRU.des_name ) {
        MemFree( SRU.des_name );
    }

    len = strlen(classname);
    SRU.con_name = MemMalloc( PB_NAME_LEN + 1 );
    GetConstructor( classname, SRU.con_name );
    SRU.des_name = MemMalloc( PB_NAME_LEN + 1 );
    GetDestructor( classname, SRU.des_name );
}


void FreeSru( void ) {
/*********************/

    statement   *curr;

    if( SRU.name ) {
        MemFree( SRU.name );
    }
    if( SRU.con_name ) {
        MemFree( SRU.con_name );
    }
    if( SRU.name ) {
        MemFree( SRU.des_name );
    }
    while( SRU.head_stmt ) {
        curr = SRU.head_stmt;
        SRU.head_stmt = curr->next;
        freeStatement( curr );
    }
    DestroyHashTable( SRU.type_prots );
    DestroyHashTable( SRU.typ_tab );
    memset( &SRU, 0, sizeof( sru_file ) ); /* clear all records */
}


void InitSru( void ) {
/********************/

    long        x;

    memset( &SRU, 0, sizeof( sru_file ) );
    inSubPgm = FALSE;
    setHeader = FALSE;
    SRU.type_prots = NewHashTable( PROTO_PRIME );
    SRU.name = MemStrDup( NONAME_FILE );
    SetDefaultAccess( ST_PUBLIC );
    SetBaseName( SRU.name );
    if( Options & OPT_GEN_C_CODE ) {
        SRU.flags |= CONSTRUCTOR_DEFINED;
        SRU.flags |= DESTRUCTOR_DEFINED;
    }
    mkConsDesNames();

    /* loads types into hash table */
    SRU.typ_tab = NewHashTable( HASH_PRIME );
    x = 0;
    while( DataTypes[x].key != NULL ) {
        InsertHashValue( SRU.typ_tab, DataTypes[x].key,
                        strlen( DataTypes[x].key ), &DataTypes[x] );
        x++;
    }
}


void SetDefaultAccess( id_type type ) {
/**************************************/

    if( inSubPgm ) {
        return;
    }
    SRU.curr_access = type;
}

void SetHeader( char *name, char *ext ) {
/***************************************/

    unsigned            headerlen;

    ext = ext;
    headerlen = strlen( SRU_HEADER );
    if( inSubPgm || setHeader || strnicmp(name, SRU_HEADER, headerlen ) ) {
        return;
    }
    assert( name );
    assert( ext );

    setHeader = TRUE;

    if( SRU.name ) {
        MemFree( SRU.name );
    }
    SRU.name = MemStrDup( name );
    strcpy( SRU.name, name + headerlen );
    SetBaseName( SRU.name );
    mkConsDesNames();
}


void UserCode( void ) {
/*********************/

    if( !inSubPgm ) {
        return;
    }

    SRU.subprog->data.sp.user_code++;
}


void SetComment( void ) {
/***********************/

    if( !inSubPgm ) {
        return;
    }
    SRU.subprog->data.sp.user_code++; /* do not put any WIG code in */
}


void SetReturn( void ) {
/**********************/

    if( !inSubPgm ) {
        return;
    }
    SRU.flags |= RETURN_STMT_PRESENT;
}

static void copyTypeInfo( TypeInfo *dst, TypeInfo *src ) {
/*********************************************************/
    if( src->name == NULL ) {
        dst->name = NULL;
    } else {
        dst->name = MemStrDup( src->name );
    }
    dst->isref = src->isref;
}

void SetFunction( TypeInfo *ret, char *fname ) {
/***********************************************/

    if( inSubPgm ) {
        return;
    }

    assert( fname );
    assert( ret );

    copyTypeInfo( &( SRU.curr.sp.ret_type ), ret );
    SRU.curr.sp.name = MemStrDup( fname );
    SRU.curr.sp.typ = ST_FUNCTION;
    SRU.curr_typ = SRU_SUBPROG;
    SRU.curr.sp.typ_id = isTypeKnown( ret ); /* we must first set sp info */
    if( !SRU.curr.sp.typ_id ) {
        /* issue warning if unknown type is found and set fake bit */
        /* only issue a warning for forward definitions so we don't issue
         * the same warning twice */
        if( SRU.sections->data.sec.primary == ST_FORWARD ) {
            Warning( UNKNOWN_TYPE, ret->name, fname );
        }
        SRU.curr.sp.fake = TRUE;
    }
}


void SetSubroutine( char *sname ) {
/*********************************/

    if( inSubPgm ) {
        return;
    }
    assert( sname );

    SRU.curr.sp.ret_type.name = NULL;
    SRU.curr.sp.ret_type.isref = FALSE;
    SRU.curr.sp.name = MemStrDup( sname );
    SRU.curr.sp.typ = ST_SUBROUTINE;
    SRU.curr.sp.subroutine = TRUE;
    SRU.curr_typ = SRU_SUBPROG;
}


void StartSubProgram( void ) {
/****************************/

/* do some house cleaning before we start processing subprograms */

    if( inSubPgm || SRU.sections ) {
        return;
    }

    if( SRU.var_sec == NULL && !(Options & OPT_GEN_C_CODE) ) {
        SRU.var_sec = appendStatement( VARIABLE_SECTION );
        appendStatement( END_VARIABLE_SECTION );
    }
    if( SRU.type_sec == NULL ) {
        SRU.type_sec = appendStatement( TYPE_PROTOTYPE_SECTION );
        appendStatement( END_PROTOTYPE_SECTION );
    }
}


void EndSubProgram( void ) {
/**************************/

/* determine wether to munge the current subprogram to make an
   external call, and then closes this subprogram
*/

    char        *line;
    var_rec     *finger;
    int         size;
    char        *ret;
    char        *name;
    statement   *curr;

    if( !inSubPgm ) {
        return;
    }

    inSubPgm = FALSE;

    assert( SRU.subprog );

    /* determine whether we should munge the  subprogram */
    if( SRU.subprog->data.sp.user_code > 1 ) {
        return;
    } else if( !(SRU.subprog->data.sp.typ_id && SRU.subprog->data.sp.ret_stmt)
                && SRU.subprog->data.sp.user_code ) {
        return;
    }

    /* munge subprogram */

    /* calculate size of statement */
    name = SRU.subprog->data.sp.name;
    size = strlen( name );
    size += sizeof(LEFT_PAREN) + sizeof(RIGHT_PAREN) + sizeof(THIS_VARIABLE);
    finger = SRU.subprog->data.sp.parm_list;
    while( finger ) {
        size += strlen( finger->name ) + sizeof( COMMA_DELIM );
        finger = finger->next;
    }
    if( !SRU.subprog->data.sp.subroutine ) {
        size += sizeof( RETURN_STATEMENT );
    }

    /* allocate memory and create function call */
    line = alloca( size );
    if( !SRU.subprog->data.sp.subroutine ) {
        ret = RETURN_STATEMENT;
    } else {
        ret = "";
    }

    finger = SRU.subprog->data.sp.parm_list;
    if( Options & OPT_GEN_C_CODE ) {
        sprintf( line, "%s%s%s", ret, name, LEFT_PAREN );
    } else {
        sprintf( line, "%s%s%s%s", ret, name, LEFT_PAREN, THIS_VARIABLE );
        if( finger ) {
            strcat( line, COMMA_DELIM );
        }
    }
    while( finger ) {
        strcat( line, finger->name );
        if( finger->next ) {
            strcat( line, COMMA_DELIM );
        }
        finger = finger->next;
    }
    strcat( line, RIGHT_PAREN );
    strcat( line, "\n" );

    /* determine where to place the new call, and place it there */
    if( SRU.subprog->data.sp.typ_id && (SRU.subprog->data.sp.user_code == 1) &&
        SRU.subprog->data.sp.ret_stmt ) {
        curr = SRU.subprog;
        while( curr && ( curr->next != SRU.subprog->data.sp.ret_stmt ) ) {
            curr = curr->next;
        }
        if( curr ) {
            replaceStatement( curr, line );
        } else {
            insertStatement( SRU.subprog, line );
        }
    } else {
        insertStatement( SRU.subprog, line );
    }
}


void FiniParmList( void ) {
/*************************/

    /* currently we do nothing */
}


void AddParm( TypeInfo *typ, char *tname, ArrayInfo *array ) {
/*************************************************************/

/* add parameter to current function's list */

    var_rec     *ptmp;

    if( inSubPgm ) {
         return;
    }

    assert( tname );
    assert( typ );

    ptmp = MemMalloc( sizeof( var_rec ) );
    memset( ptmp, 0, sizeof( var_rec ) );
    if( SRU.curr.sp.last_parm ) {
        SRU.curr.sp.last_parm->next = ptmp;
    } else {
        SRU.curr.sp.parm_list = ptmp;
    }
    SRU.curr.sp.last_parm = ptmp;
    copyTypeInfo( &ptmp->type, typ );
    ptmp->typ_id = isTypeKnown( typ );
    if( !ptmp->typ_id ) {
        ptmp->fake = TRUE;
    }
    ptmp->next = NULL;
    ptmp->name = MemStrDup( tname );
    if( array == NULL ) {
        ptmp->array = NULL;
    } else {
        ptmp->array = MemMalloc( sizeof( ArrayInfo ) );
        memcpy( ptmp->array, array, sizeof( ArrayInfo ) );
    }
}


void StartSection( id_type ptyp, id_type styp ) {
/***********************************************/

    if( inSubPgm ) {
         return;
    }

    SRU.curr.sec.primary = ptyp;
    SRU.curr.sec.secondary = styp;
    SRU.curr_typ = SRU_SECTION;
    if( styp == ST_VARIABLES ) {
        if( ptyp == ST_SHARED ) {
            SetDefaultAccess( ST_PRIVATE );
        } else if( ptyp == ST_TYPE ) {
            SetDefaultAccess( ST_PUBLIC );
        }
    }
}


void EndSection(void) {
/*********************/

    if( inSubPgm ) {
         return;
    }

    if( SRU.sections ) {
        SRU.sections = SRU.sections->link;

⌨️ 快捷键说明

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