示例#1
0
static ret_code CloseSeg( const char *name )
/******************************************/
{
    //struct asym      *sym;

    DebugMsg1(("CloseSeg(%s) enter\n", name));

    if( CurrSeg == NULL || ( SymCmpFunc( CurrSeg->sym.name, name, CurrSeg->sym.name_size ) != 0 ) ) {
        DebugMsg(("CloseSeg(%s): nesting error, CurrSeg=%s\n", name, CurrSeg ? CurrSeg->sym.name : "(null)" ));
        EmitErr( BLOCK_NESTING_ERROR, name );
        return( ERROR );
    }

    DebugMsg1(("CloseSeg(%s): current ofs=%" FX32 "\n", name, CurrSeg->e.seginfo->current_loc));

    if ( write_to_file && ( Options.output_format == OFORMAT_OMF ) ) {

        //if ( !omf_FlushCurrSeg() ) /* v2: error check is obsolete */
        //    EmitErr( INTERNAL_ERROR, "CloseSeg", 1 ); /* coding error! */
        omf_FlushCurrSeg();
        if ( Options.no_comment_data_in_code_records == FALSE )
            omf_OutSelect( FALSE );
    }

    pop_seg();

    return( NOT_ERROR );
}
示例#2
0
/* Called by SetModel() [.MODEL directive].
 * Initializes simplified segment directives.
 * NewLineQueue() has already been called,
 * and the caller will run RunLineQueue() later.
 * Called for each pass.
 */
ret_code ModelSimSegmInit( int model )
/************************************/
{
    char buffer[20];

    if ( Parse_Pass == PASS_1 ) {
        DebugMsg1(("ModelSimSegmInit() enter, pass one\n" ));
        /* create default code segment (_TEXT) */
        SetSimSeg( SIM_CODE, NULL );
        EndSimSeg( SIM_CODE );

        /* create default data segment (_DATA) */
        SetSimSeg( SIM_DATA, NULL ) ;
        EndSimSeg( SIM_DATA );

        /* create DGROUP for BIN/OMF if model isn't FLAT */
        if( model != MODEL_FLAT &&
            ( Options.output_format == OFORMAT_OMF ||
             Options.output_format == OFORMAT_BIN )) {
            strcpy( buffer, "%s %r %s" );
            if( model == MODEL_TINY ) {
                strcat( buffer, ", %s" );
                AddLineQueueX( buffer, szDgroup, T_GROUP, SegmNames[SIM_CODE], SegmNames[SIM_DATA] );
            } else
                AddLineQueueX( buffer, szDgroup, T_GROUP, SegmNames[SIM_DATA] );
        }
        DebugMsg1(("ModelSimSegmInit() exit\n" ));
    }
    return( NOT_ERROR );
}
示例#3
0
static ret_code SetCurrSeg( int i, struct asm_tok tokenarray[] )
/**************************************************************/
{
    struct asym *sym;

    sym = SymSearch( tokenarray[0].string_ptr );
    DebugMsg1(("SetCurrSeg(%s) sym=%p\n", tokenarray[0].string_ptr, sym));
    if ( sym == NULL || sym->state != SYM_SEG ) {
        EmitErr( SEG_NOT_DEFINED, tokenarray[0].string_ptr );
        return( ERROR );
    }
    /* v2.04: added */
    sym->isdefined = TRUE;
    if ( CurrSeg && Options.output_format == OFORMAT_OMF ) {
        omf_FlushCurrSeg();
        if ( Options.no_comment_data_in_code_records == FALSE )
            omf_OutSelect( FALSE );
    }
    push_seg( (struct dsym *)sym );

    if ( ModuleInfo.list )
        LstWrite( LSTTYPE_LABEL, 0, NULL );

    return( SetOfssize() );
}
示例#4
0
文件: input.c 项目: JWasm/JWasm
void PushMacro( struct macro_instance *mi )
/*****************************************/
{
    DebugMsg1(( "PushMacro(%s)\n", mi->macro->name ));
    PushSrcItem( SIT_MACRO, mi );
    return;
}
示例#5
0
文件: input.c 项目: JWasm/JWasm
struct asm_tok *PushInputStatus( struct input_status *oldstat )
/*************************************************************/
{
    oldstat->token_stringbuf = token_stringbuf;
    oldstat->token_count = Token_Count;
    oldstat->currsource = CurrSource;
    /* if there's a comment, attach it to current source */
    if ( ModuleInfo.CurrComment ) {
        int i = strlen( CurrSource );
        oldstat->CurrComment = CurrSource + i;
        strcpy( oldstat->CurrComment, ModuleInfo.CurrComment );
    } else
        oldstat->CurrComment = NULL;
    oldstat->line_flags = ModuleInfo.line_flags; /* v2.08 */
#ifdef __I86__
    oldstat->tokenarray = ModuleInfo.tokenarray;
    oldstat->stringbufferend = StringBufferEnd;
    CurrSource = MemAlloc( MAX_LINE_LEN + SIZE_TOKENARRAY + SIZE_STRINGBUFFER );
    ModuleInfo.tokenarray = (struct asm_tok *)( CurrSource + MAX_LINE_LEN );
    token_stringbuf = CurrSource + MAX_LINE_LEN + SIZE_TOKENARRAY;
#else
    token_stringbuf = StringBufferEnd;
    ModuleInfo.tokenarray += Token_Count + 1;
    CurrSource = GetAlignedPointer( CurrSource, strlen( CurrSource ) );
    /**/myassert( ( CurrSource + MAX_LINE_LEN ) <= (char *)ModuleInfo.tokenarray );
    /**/myassert( ( ModuleInfo.tokenarray + sizeof( struct asm_tok ) * MAX_TOKEN ) <= end_tokenarray );
    /**/myassert( ( token_stringbuf + 2 * MAX_LINE_LEN ) <= end_stringbuf );
#endif
    DebugMsg1(("PushInputStatus() stringbuf-tokencnt-currsrc old=%X-%u-%X new=%X-%X-%X\n",
               oldstat->token_stringbuf, oldstat->token_count, oldstat->currsource,
               token_stringbuf, ModuleInfo.tokenarray, CurrSource ));
    return( ModuleInfo.tokenarray );
}
示例#6
0
文件: input.c 项目: JWasm/JWasm
void PopInputStatus( struct input_status *newstat )
/*************************************************/
{
    DebugMsg1(("PopInputStatus() old=%X-%u-%X new=%X-%u-%X\n",
               token_stringbuf, Token_Count, CurrSource,
               newstat->token_stringbuf, newstat->token_count, newstat->currsource ));
#ifdef __I86__
    MemFree( CurrSource );
#else
    StringBufferEnd = token_stringbuf;
#endif
    token_stringbuf = newstat->token_stringbuf;
    Token_Count = newstat->token_count;
    CurrSource = newstat->currsource;
    if ( newstat->CurrComment ) {
        ModuleInfo.CurrComment = commentbuffer;
        strcpy( ModuleInfo.CurrComment, newstat->CurrComment );
        *newstat->CurrComment = NULLC;
    } else
        ModuleInfo.CurrComment = NULL;
#ifdef __I86__
    StringBufferEnd = newstat->stringbufferend;
    ModuleInfo.tokenarray = newstat->tokenarray;
#else
    ModuleInfo.tokenarray -= Token_Count + 1;
#endif
    ModuleInfo.line_flags = newstat->line_flags; /* v2.08 */
    return;
}
示例#7
0
static void UpdateCurrSegVars( void )
/***********************************/
{
    struct assume_info *info;

    DebugMsg1(("UpdateCurrSegVars(%s)\n", CurrSeg ? CurrSeg->sym.name : "NULL" ));
    info = &(SegAssumeTable[ ASSUME_CS ]);
    if( CurrSeg == NULL ) {
        info->symbol = NULL;
        info->flat = FALSE;
        info->error = TRUE;
        symCurSeg->string_ptr = "";
        //symPC.segment = NULL; /* v2.05: removed */
    } else {
        info->flat = FALSE;
        info->error = FALSE;
        /* fixme: OPTION OFFSET:SEGMENT? */
        if( CurrSeg->e.seginfo->group != NULL ) {
            info->symbol = CurrSeg->e.seginfo->group;
            if ( info->symbol == &ModuleInfo.flat_grp->sym )
                info->flat = TRUE;
        } else {
            info->symbol = &CurrSeg->sym;
        }
        symCurSeg->string_ptr = CurrSeg->sym.name;
        //symPC.segment = &CurrSeg->sym; /* v2.05: removed */
    }
    return;
}
示例#8
0
static void close_currseg( void )
/*******************************/
{
    if ( CurrSeg ) {
        DebugMsg1(("close_currseg: current seg=%s\n", CurrSeg->sym.name));
        AddLineQueueX( "%s %r", CurrSeg->sym.name, T_ENDS );
    }
}
示例#9
0
文件: input.c 项目: JWasm/JWasm
/* function to get value of @FileCur.
 * won't work, because text macros don't use asym.sfunc_ptr
 */
static void GetFileCur( struct asym *sym )
/****************************************/
{
    struct src_item *curr;

    for( curr = src_stack; curr && curr->type != SIT_FILE; curr = curr->next );
    sym->string_ptr = GetFName( curr->srcfile )->name;
    DebugMsg1(("GetFileCur: curr value=%s\n", sym->string_ptr ));
}
示例#10
0
文件: input.c 项目: JWasm/JWasm
char *GetTextLine( char *buffer )
/*******************************/
{
    struct src_item *curr = src_stack;

    if ( curr->type == SIT_FILE ) {

        if( my_fgets( buffer, MAX_LINE_LEN, curr->file ) ) {
            curr->line_num++;
#ifdef DEBUG_OUT
            if ( Parse_Pass == PASS_1 ) cntlines++;
#endif
            return( buffer );
        }
        DebugCmd( ModuleInfo.g.FNames[curr->srcfile].lines = curr->line_num );
        DebugMsg1(("GetTextLine: ***** EOF file %s (idx=%u) *****\n", GetFName( curr->srcfile )->fname, curr->srcfile ));
        /* don't close and remove main source file */
        if ( curr->next ) {
            fclose( curr->file );
            src_stack = curr->next;
            curr->next = SrcFree;
            SrcFree = curr;
        }
        /* update value of @FileCur variable */
        for( curr = src_stack; curr->type != SIT_FILE; curr = curr->next );
        FileCur->string_ptr = GetFName( curr->srcfile)->fname;
#if FILESEQ
        if ( Options.line_numbers && Parse_Pass == PASS_1 )
            AddFileSeq( curr->srcfile );
#endif

    } else {

        curr->mi->currline = ( curr->mi->currline ? curr->mi->currline->next : curr->mi->startline );
        if ( curr->mi->currline ) {
            /* if line contains placeholders, replace them by current values */
            if ( curr->mi->currline->ph_count ) {
                fill_placeholders( buffer,
                                  curr->mi->currline->line,
                                  curr->mi->parmcnt,
                                  curr->mi->localstart, curr->mi->parm_array );
            } else {
                strcpy( buffer, curr->mi->currline->line );
            }
            curr->line_num++;
#ifdef DEBUG_OUT
            if ( Parse_Pass == PASS_1 ) cntlines++;
#endif
            return( buffer );
        }
        src_stack = curr->next;
        curr->next = SrcFree;
        SrcFree = curr;
    }

    return( NULL ); /* end of file or macro reached */
}
示例#11
0
static ret_code SubStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] )
/************************************************************************************************/
{
    int pos;
    int size;
    char *src = mi->parm_array[0];

    DebugMsg1(("@SubStr( %s, %s, %s)\n",
              src ? src : "",
              mi->parm_array[1] ? mi->parm_array[1] : "",
              mi->parm_array[2] ? mi->parm_array[2] : "" ));

    if ( GetNumber( mi->parm_array[1], &pos, tokenarray ) == ERROR )
        return( ERROR );

    if ( pos <= 0 ) {
        /* Masm doesn't check if index is < 0;
         * might cause an "internal assembler error".
         * v2.09: negative index no longer silently changed to 1.
         */
        if ( pos ) {
            return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) );
        }
        DebugMsg(( "@SubStr(): index value 0 changed to 1\n", pos ));
        pos = 1;
    }

    size = strlen( src );
    if ( pos > size ) {
        return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) );
    }

    size = size - pos + 1;

    if ( mi->parm_array[2] ) {
        int sizereq;
        if ( GetNumber( mi->parm_array[2], &sizereq, tokenarray ) == ERROR )
            return( ERROR );
        if ( sizereq < 0 ) {
            return( EmitError( COUNT_MUST_BE_POSITIVE_OR_ZERO ) );
        }
        if ( sizereq > size ) {
            return( EmitError( COUNT_VALUE_TOO_LARGE ) );
        }
        size = sizereq;
    }
#if 1
    memcpy( buffer, src + pos - 1, size );
    *(buffer+size) = NULLC;
#else
    for( src += pos - 1; size; size-- )
        *buffer++ = *src++;
    *buffer = NULLC;
#endif
    return( NOT_ERROR );
}
示例#12
0
/* internal @InStr macro function
 * syntax: @InStr( [num], literal, literal )
 * the result is returned as string in current radix
 */
static ret_code InStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] )
/***********************************************************************************************/
{
    int pos = 1;
    char *p;
    uint_32 found;

    DebugMsg1(("@InStr( %s, %s, %s)\n",
              mi->parm_array[0] ? mi->parm_array[0] : "",
              mi->parm_array[1] ? mi->parm_array[1] : "",
              mi->parm_array[2] ? mi->parm_array[2] : "" ));

    /* init buffer with "0" */
    *buffer = '0';
    *(buffer+1) = NULLC;

    if ( mi->parm_array[0] ) {
        if ( GetNumber( mi->parm_array[0], &pos, tokenarray ) == ERROR )
            return( ERROR );
        if ( pos == 0 ) {
            /* adjust index 0. Masm also accepts 0 (and any negative index),
             * but the result will always be 0 then */
            DebugMsg(( "@InStr(): index value is 0, changed to 1\n" ));
            pos++;
        }
    }

    if ( pos > strlen( mi->parm_array[1] ) ) {
        return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) );
    }
    /* v2.08: if() added, empty searchstr is to return 0 */
    if ( *(mi->parm_array[2]) != NULLC ) {
        p = strstr( mi->parm_array[1] + pos - 1, mi->parm_array[2] );
        if ( p ) {
            found = p - mi->parm_array[1] + 1;
            myltoa( found, buffer, ModuleInfo.radix, FALSE, TRUE );
        }
    }

    DebugMsg1(( "@InStr()=>%s<\n", buffer ));

    return( NOT_ERROR );
}
示例#13
0
static struct asym *CreateProto( int i, struct asm_tok tokenarray[], const char *name, enum lang_type langtype )
/**************************************************************************************************************/
{
    struct asym      *sym;
    struct dsym      *dir;

    DebugMsg1(("CreateProto( i=%u, name=%s, lang=%u )\n", i, name ? name : "NULL", langtype ));
    sym = SymSearch( name );

    /* the symbol must be either NULL or state
     * - SYM_UNDEFINED
     * - SYM_EXTERNAL + isproc == FALSE ( previous EXTERNDEF )
     * - SYM_EXTERNAL + isproc == TRUE ( previous PROTO )
     * - SYM_INTERNAL + isproc == TRUE ( previous PROC )
     */
    if( sym == NULL ||
       sym->state == SYM_UNDEFINED ||
       ( sym->state == SYM_EXTERNAL && sym->weak == TRUE && sym->isproc == FALSE )) {
        if ( NULL == ( sym = CreateProc( sym, name, SYM_EXTERNAL ) ) )
            return( NULL ); /* name was probably invalid */
    } else if ( sym->isproc == FALSE ) {
        EmitErr( SYMBOL_REDEFINITION, sym->name );
        return( NULL );
    }
    dir = (struct dsym *)sym;

    /* a PROTO typedef may be used */
    if ( tokenarray[i].token == T_ID ) {
        struct asym * sym2;
        sym2 = SymSearch( tokenarray[i].string_ptr );
        if ( sym2 && sym2->state == SYM_TYPE && sym2->mem_type == MT_PROC ) {
            i++;
            if ( tokenarray[i].token != T_FINAL ) {
                EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
                return( NULL );
            }
            CopyPrototype( dir, (struct dsym *)sym2->target_type );
            return( sym );
        }
    }
    /* sym->isproc is set inside ParseProc() */
    //sym->isproc = TRUE;

    if ( Parse_Pass == PASS_1 ) {
        if ( ParseProc( dir, i, tokenarray, FALSE, langtype ) == ERROR )
            return( NULL );
#if DLLIMPORT
        sym->dll = ModuleInfo.CurrDll;
#endif
    } else {
        sym->isdefined = TRUE;
    }
    return( sym );
}
示例#14
0
static ret_code CatStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] )
/************************************************************************************************/
{
#ifdef DEBUG_OUT
    int cnt = 0;
#endif
    int i;
    char *p;

    DebugMsg1(("@CatStr( %s )\n", mi->parm_array[0] ? mi->parm_array[0] : "NULL" ));

    for ( p = mi->parm_array[0]; mi->parmcnt; mi->parmcnt-- ) {
        DebugMsg1(("@CatStr.%u: >%s<\n", cnt++, p ));
        i = strlen( p );
        memcpy( buffer, p, i );
        p = GetAlignedPointer( p, i );
        buffer += i;
    }
    *buffer = NULLC;
    return( NOT_ERROR );
}
示例#15
0
/* internal @SizeStr macro function
 * syntax: @SizeStr( literal )
 * the result is returned as string in current radix
 */
static ret_code SizeStrFunc( struct macro_instance *mi, char *buffer, struct asm_tok tokenarray[] )
/*************************************************************************************************/
{
    DebugMsg1(("@SizeStr(%s)\n", mi->parm_array[0] ? mi->parm_array[0] : "" ));
    if ( mi->parm_array[0] )
        myltoa( strlen( mi->parm_array[0] ), buffer, ModuleInfo. radix, FALSE, TRUE );
    else {
        buffer[0] = '0';
        buffer[1] = NULLC;
    }
    return( NOT_ERROR );
}
示例#16
0
/* SizeStr()
 * defines a numeric variable which contains size of a string
 */
ret_code SizeStrDir( int i, struct asm_tok tokenarray[] )
/*******************************************************/
{
    struct asym *sym;
    int sizestr;

    DebugMsg1(("SizeStrDir entry\n"));
    DebugCmd( sizstrcnt++ );

    if ( i != 1 ) {
        return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
    }
#if 0 /* this is checked in ParseLine() */
    if ( tokenarray[0].token != T_ID ) {
        return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) );
    }
#endif
    if ( tokenarray[2].token != T_STRING || tokenarray[2].string_delim != '<' ) {
        return( TextItemError( &tokenarray[2] ) );
    }
    if ( Token_Count > 3 ) {
        DebugMsg(("SizeStrDir: syntax error, name=%s, Token_Count=%u\n", tokenarray[0].string_ptr, Token_Count));
        return( EmitErr( SYNTAX_ERROR_EX, tokenarray[3].string_ptr ) );
    }

    //sizestr = GetLiteralValue( StringBufferEnd, tokenarray[2].string_ptr );
    sizestr = tokenarray[2].stringlen;

    if ( sym = CreateVariable( tokenarray[0].string_ptr, sizestr ) ) {
        DebugMsg1(("SizeStrDir(%s) exit, value=%u\n", tokenarray[0].string_ptr, sizestr));
        LstWrite( LSTTYPE_EQUATE, 0, sym );
        return( NOT_ERROR );
    }
    return( ERROR );

}
示例#17
0
void SetCurPC( struct asym *sym )
/*******************************/
{
    if( CurrStruct ) {
        //symPC.segment = NULL;
        //symPC.mem_type = MT_ABS;
        symPC.mem_type = MT_EMPTY;
        symPC.segment = NULL; /* v2.07: needed again */
        symPC.offset = CurrStruct->sym.offset + (CurrStruct->next ? CurrStruct->next->sym.offset : 0);
    } else {
        symPC.mem_type = MT_NEAR;
        symPC.segment = (struct asym *)CurrSeg;
        symPC.offset = GetCurrOffset();
    }
    DebugMsg1(("SetCurPC: curr value=%" FX32 "h\n", symPC.offset ));
}
示例#18
0
/* create a (predefined) text macro.
 * used to create @code, @data, ...
 * there are 2 more locations where predefined text macros may be defined:
 * - assemble.c, add_cmdline_tmacros()
 * - symbols.c, SymInit()
 * this should be changed eventually.
 */
struct asym *AddPredefinedText( const char *name, const char *value )
/*******************************************************************/
{
    struct asym *sym;

    DebugMsg1(("AddPredefinedText(%s): >%s<\n", name, value ));
    /* v2.08: ignore previous setting */
    if ( NULL == ( sym = SymSearch( name ) ) )
        sym = SymCreate( name );
    sym->state = SYM_TMACRO;
    sym->isdefined = TRUE;
    sym->predefined = TRUE;
    sym->string_ptr = (char *)value;
    /* to ensure that a new buffer is used if the string is modified */
    sym->total_size = 0;
    return( sym );
}
示例#19
0
文件: input.c 项目: JWasm/JWasm
/* check if a file is in the array of known files.
 * if no, store the file at the array's end.
 * returns array index.
 * used for the main source and all INCLUDEd files.
 * the array is stored in the standard C heap!
 * the filenames are stored in the "local" heap.
 */
static unsigned AddFile( char const *fname )
/******************************************/
{
    unsigned    index;

    DebugMsg1(("AddFile(%s) enter, curr index=%u\n", fname, ModuleInfo.g.cnt_fnames ));
    for( index = 0; index < ModuleInfo.g.cnt_fnames; index++ ) {
        if( filecmp( fname, ModuleInfo.g.FNames[index].fname ) == 0 ) {
#ifdef DEBUG_OUT
            if ( Parse_Pass == PASS_1 )
                ModuleInfo.g.FNames[index].included++;
#endif
            return( index );
        }
    }

    if ( ( index % 64 ) == 0 ) {
        struct fname_item *newfn;
        newfn = (struct fname_item *)MemAlloc( ( index + 64 ) * sizeof( struct fname_item ) );
        if ( ModuleInfo.g.FNames ) {
            memcpy( newfn, ModuleInfo.g.FNames, index * sizeof( struct fname_item ) );
            MemFree( ModuleInfo.g.FNames );
        }
        ModuleInfo.g.FNames = newfn;
    }
    ModuleInfo.g.cnt_fnames++;

    /* v2.11: use name directly - allows COFF .file entries with relative paths */
    //_splitpath( fname, NULL, NULL, name, ext );

    ModuleInfo.g.FNames[index].fname = (char *)LclAlloc( strlen( fname ) + 1 );
    strcpy( ModuleInfo.g.FNames[index].fname, fname );
    /* v2.11: field fullname removed */
    //ModuleInfo.g.FNames[index].fullname = (char *)LclAlloc( strlen( fullname ) + 1 );
    //strcpy( ModuleInfo.g.FNames[index].fullname, fullname );
    DebugCmd( ModuleInfo.g.FNames[index].included = 1 );
    return( index );
}
示例#20
0
ret_code CommDirective( int i, struct asm_tok tokenarray[] )
/**********************************************************/
{
    char            *token;
#if MANGLERSUPP
    char            *mangle_type = NULL;
#endif
    bool            isfar;
    //int             distance;
    int             tmp;
    uint_32         size;  /* v2.12: changed from 'int' to 'uint_32' */
    uint_32         count; /* v2.12: changed from 'int' to 'uint_32' */
    struct asym     *sym;
    struct expr     opndx;
    enum lang_type  langtype;

    DebugMsg1(("CommDirective(%u) enter\n", i));
    i++; /* skip COMM token */
    for( ; i < Token_Count; i++ ) {
#if MANGLERSUPP
        mangle_type = Check4Mangler( &i, tokenarray );
#endif
        /* get the symbol language type if present */
        langtype = ModuleInfo.langtype;
        GetLangType( &i, tokenarray, &langtype );

        /* get the -optional- distance ( near or far ) */
        isfar = FALSE;
        if ( tokenarray[i].token == T_STYPE )
            switch ( tokenarray[i].tokval ) {
            case T_FAR:
            case T_FAR16:
            case T_FAR32:
                if ( ModuleInfo.model == MODEL_FLAT ) {
                    EmitError( FAR_NOT_ALLOWED_IN_FLAT_MODEL_COMM_VARIABLES );
                } else
                    isfar = TRUE;
                /* no break */
            case T_NEAR:
            case T_NEAR16:
            case T_NEAR32:
                i++;
            }

        /* v2.08: ensure token is a valid id */
        if( tokenarray[i].token != T_ID ) {
            return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
        }
        /* get the symbol name */
        token = tokenarray[i++].string_ptr;

        /* go past the colon */
        if( tokenarray[i].token != T_COLON ) {
            return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
        }
        i++;
        /* the evaluator cannot handle a ':' so scan for one first */
        for ( tmp = i; tmp < Token_Count;tmp++ )
            if ( tokenarray[tmp].token == T_COLON )
                break;
        /* v2.10: expression evaluator isn't to accept forward references */
        //if ( EvalOperand( &i, tokenarray, tmp, &opndx, 0 ) == ERROR )
        if ( EvalOperand( &i, tokenarray, tmp, &opndx, EXPF_NOUNDEF ) == ERROR )
            return( ERROR );

        /* v2.03: a string constant is accepted by Masm */
        /* v2.11: don't accept NEAR or FAR */
        /* v2.12: check for too large value added */
        //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) {
        if ( opndx.kind != EXPR_CONST )
            EmitError( CONSTANT_EXPECTED );
        else if ( ( opndx.mem_type & MT_SPECIAL_MASK) == MT_ADDRESS )
            EmitErr( INVALID_TYPE_FOR_DATA_DECLARATION, token );
        else if ( opndx.hvalue != 0 && opndx.hvalue != -1 )
            EmitConstError( &opndx );
        else if ( opndx.uvalue == 0 )
            EmitError( POSITIVE_VALUE_EXPECTED );

        size = opndx.uvalue;

        count = 1;
        if( tokenarray[i].token == T_COLON ) {
            i++;
            /* get optional count argument */
            /* v2.10: expression evaluator isn't to accept forward references */
            //if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR )
            if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR )
                return( ERROR );

            /* v2.03: a string constant is acceptable! */
            /* v2.12: check for too large value added */
            //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) {
            if ( opndx.kind != EXPR_CONST )
                EmitError( CONSTANT_EXPECTED );
            else if ( opndx.hvalue != 0 && opndx.hvalue != -1 )
                EmitConstError( &opndx );
            else if ( opndx.uvalue == 0 )
                EmitError( POSITIVE_VALUE_EXPECTED );

            count = opndx.uvalue;
        }

        sym = SymSearch( token );
        if( sym == NULL || sym->state == SYM_UNDEFINED ) {
            sym = MakeComm( token, sym, size, count, isfar );
            if ( sym == NULL )
                return( ERROR );
        } else if ( sym->state != SYM_EXTERNAL || sym->iscomm != TRUE ) {
            return( EmitErr( SYMBOL_REDEFINITION, sym->name ) );
        } else {
            tmp = sym->total_size / sym->total_length;
            if( count != sym->total_length || size != tmp ) {
                return( EmitErr( NON_BENIGN_XXX_REDEFINITION, szCOMM, sym->name ) );
            }
        }
        sym->isdefined = TRUE;
        SetMangler( sym, langtype, mangle_type );

        if ( tokenarray[i].token != T_FINAL && tokenarray[i].token != T_COMMA ) {
            return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) );
        }
    }
    return( NOT_ERROR );
}
示例#21
0
ret_code ExternDirective( int i, struct asm_tok tokenarray[] )
/************************************************************/
{
    char                *token;
#if MANGLERSUPP
    char                *mangle_type = NULL;
#endif
    char                *altname;
    struct asym         *sym;
    enum lang_type      langtype;
    struct qualified_type ti;

    DebugMsg1(("ExternDirective(%u) enter\n", i));
    i++; /* skip EXT[E]RN token */
#if MANGLERSUPP
    mangle_type = Check4Mangler( &i, tokenarray );
#endif
    do {

        altname = NULL;

        /* get the symbol language type if present */
        langtype = ModuleInfo.langtype;
        GetLangType( &i, tokenarray, &langtype );

        /* get the symbol name */
        if( tokenarray[i].token != T_ID ) {
            return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
        }
        token = tokenarray[i++].string_ptr;

        /* go past the optional alternative name (weak ext, default resolution) */
        if( tokenarray[i].token == T_OP_BRACKET ) {
            i++;
            if ( tokenarray[i].token != T_ID ) {
                return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
            }
            altname = tokenarray[i].string_ptr;
            i++;
            if( tokenarray[i].token != T_CL_BRACKET ) {
                return( EmitErr( EXPECTED, ")" ) );
            }
            i++;
        }

        /* go past the colon */
        if( tokenarray[i].token != T_COLON ) {
            return( EmitError( COLON_EXPECTED ) );
        }
        i++;
        sym = SymSearch( token );

        ti.mem_type = MT_EMPTY;
        ti.size = 0;
        ti.is_ptr = 0;
        ti.is_far = FALSE;
        ti.ptr_memtype = MT_EMPTY;
        ti.symtype = NULL;
        ti.Ofssize = ModuleInfo.Ofssize;

        if ( tokenarray[i].token == T_ID && ( 0 == _stricmp( tokenarray[i].string_ptr, "ABS" ) ) ) {
            //ti.mem_type = MT_ABS;
            i++;
        } else if ( tokenarray[i].token == T_DIRECTIVE && tokenarray[i].tokval == T_PROTO ) {
            /* dont scan this line further */
            /* CreateProto() will define a SYM_EXTERNAL */
            sym = CreateProto( i + 1, tokenarray, token, langtype );
            DebugMsg1(("ExternDirective(%s): CreateProto()=%X\n", token, sym));
            if ( sym == NULL )
                return( ERROR );
            if ( sym->state == SYM_EXTERNAL ) {
                sym->weak = FALSE;
                return( HandleAltname( altname, sym ) );
            } else {
                /* unlike EXTERNDEF, EXTERN doesn't allow a PROC for the same name */
                return( EmitErr( SYMBOL_REDEFINITION, sym->name ) );
            }
        } else if ( tokenarray[i].token != T_FINAL && tokenarray[i].token != T_COMMA ) {
            if ( GetQualifiedType( &i, tokenarray, &ti ) == ERROR )
                return( ERROR );
        }

        DebugMsg1(("ExternDirective(%s): mem_type=%Xh\n", token, ti.mem_type ));

        if( sym == NULL || sym->state == SYM_UNDEFINED ) {
            /* v2.04: emit the error at the PUBLIC directive */
            //if ( sym && sym->public == TRUE ) {
            //    EmitErr( CANNOT_DEFINE_AS_PUBLIC_OR_EXTERNAL, sym->name );
            //    return( ERROR );
            //}
            if(( sym = MakeExtern( token, ti.mem_type,
                                  ti.mem_type == MT_TYPE ? ti.symtype : NULL, sym,
                                  ti.is_ptr ? ModuleInfo.Ofssize : ti.Ofssize )) == NULL )
                return( ERROR );

            /* v2.05: added to accept type prototypes */
            if ( ti.is_ptr == 0 && ti.symtype && ti.symtype->isproc ) {
                CreateProc( sym, NULL, SYM_EXTERNAL );
                sym->weak = FALSE; /* v2.09: reset the weak bit that has been set inside CreateProc() */
                CopyPrototype( (struct dsym *)sym, (struct dsym *)ti.symtype );
                ti.mem_type = ti.symtype->mem_type;
                ti.symtype = NULL;
                DebugMsg1(("ExternDirective(%s): prototype copied, memtype=%X\n", token, ti.mem_type ));
            }

        } else {
#if MASM_EXTCOND
            /* allow internal AND external definitions for equates */
            //if ( sym->state == SYM_INTERNAL && sym->mem_type == MT_ABS )
            if ( sym->state == SYM_INTERNAL && sym->mem_type == MT_EMPTY )
                ;
            else
#endif
            if ( sym->state != SYM_EXTERNAL ) {
                DebugMsg(("ExternDirective: symbol %s redefinition, state=%u\n", token, sym->state ));
                return( EmitErr( SYMBOL_REDEFINITION, token ) );
            }
            /* v2.05: added to accept type prototypes */
            if ( ti.is_ptr == 0 && ti.symtype && ti.symtype->isproc ) {
                ti.mem_type = ti.symtype->mem_type;
                ti.symtype = NULL;
            }

            if( sym->mem_type != ti.mem_type ||
               sym->is_ptr != ti.is_ptr ||
               sym->isfar != ti.is_far ||
               ( sym->is_ptr && sym->ptr_memtype != ti.ptr_memtype ) ||
               ((sym->mem_type == MT_TYPE) ? sym->type : sym->target_type) != ti.symtype ||
               ( langtype != LANG_NONE && sym->langtype != LANG_NONE && sym->langtype != langtype )) {
                DebugMsg(("ExternDirective: memtype:%X-%X ptr=%X-%X far=%X-%X ptr_memtype=%X-%X lang=%u-%u\n",
                          sym->mem_type, ti.mem_type,
                          sym->is_ptr, ti.is_ptr,
                          sym->isfar, ti.is_far,
                          sym->ptr_memtype, ti.ptr_memtype,
                          sym->langtype, langtype
                         ));
                return( EmitErr( SYMBOL_TYPE_CONFLICT, token ) );
            }
        }

        sym->isdefined = TRUE;
        sym->Ofssize = ti.Ofssize;

        if ( ti.is_ptr == 0 && ti.Ofssize != ModuleInfo.Ofssize ) {
            sym->seg_ofssize = ti.Ofssize;
            if ( sym->segment && ((struct dsym *)sym->segment)->e.seginfo->Ofssize != sym->seg_ofssize )
                sym->segment = NULL;
        }

        sym->mem_type = ti.mem_type;
        sym->is_ptr = ti.is_ptr;
        sym->isfar = ti.is_far;
        sym->ptr_memtype = ti.ptr_memtype;
        if ( ti.mem_type == MT_TYPE )
            sym->type = ti.symtype;
        else
            sym->target_type = ti.symtype;

        HandleAltname( altname, sym );

        SetMangler( sym, langtype, mangle_type );

        if ( tokenarray[i].token != T_FINAL )
            if ( tokenarray[i].token == T_COMMA &&  ( (i + 1) < Token_Count ) ) {
                i++;
            } else {
                return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
            }
    }  while ( i < Token_Count );

    return( NOT_ERROR );
}
示例#22
0
static ret_code HandleAltname( char *altname, struct asym *sym )
/**************************************************************/
{
    struct asym *symalt;

    if ( altname && sym->state == SYM_EXTERNAL ) {

        symalt = SymSearch( altname );

        /* altname symbol changed? */
        if ( sym->altname && sym->altname != symalt ) {
            return( EmitErr( SYMBOL_REDEFINITION, sym->name ) );
        }

        if ( Parse_Pass > PASS_1 ) {
            if ( symalt->state == SYM_UNDEFINED ) {
                EmitErr( SYMBOL_NOT_DEFINED, altname );
            } else if (symalt->state != SYM_INTERNAL && symalt->state != SYM_EXTERNAL ) {
                EmitErr( SYMBOL_TYPE_CONFLICT, altname );
            } else {
#if COFF_SUPPORT || ELF_SUPPORT
                if ( symalt->state == SYM_INTERNAL && symalt->ispublic == FALSE )
                    if ( Options.output_format == OFORMAT_COFF
#if ELF_SUPPORT
                        || Options.output_format == OFORMAT_ELF
#endif
                       ) {
                        EmitErr( MUST_BE_PUBLIC_OR_EXTERNAL, altname );
                    }
#endif
                if ( sym->mem_type != symalt->mem_type )
                    EmitErr( SYMBOL_TYPE_CONFLICT, altname );
            }
        } else {

            if ( symalt ) {
                DebugMsg(("HandleAltname: symbol '%s' found, state=%u\n", altname, symalt->state ));
                if ( symalt->state != SYM_INTERNAL &&
                    symalt->state != SYM_EXTERNAL &&
                    symalt->state != SYM_UNDEFINED ) {
                    return( EmitErr( SYMBOL_TYPE_CONFLICT, altname ) );
                }
            } else {
                symalt = SymCreate( altname );
                sym_add_table( &SymTables[TAB_UNDEF], (struct dsym *)symalt );
            }
            /* make sure the alt symbol becomes strong if it is an external
             * v2.11: don't do this for OMF ( maybe neither for COFF/ELF? )
             */
            if ( Options.output_format != OFORMAT_OMF )
                symalt->used = TRUE;
            /* symbol inserted in the "weak external" queue?
             * currently needed for OMF only.
             */
            if ( sym->altname == NULL ) {
                sym->altname = symalt;
#if 0 /* v2.11: removed. Member nextext wasn't free to use */
                DebugMsg1(("HandleAltname: symbol '%s' added to AltQueue\n", sym->name ));
                ((struct dsym *)sym)->nextext = NULL;
                if ( ModuleInfo.g.AltQueue.head == NULL )
                    ModuleInfo.g.AltQueue.head = ModuleInfo.g.AltQueue.tail = (struct dsym *)sym;
                else {
                    ((struct dsym *)ModuleInfo.g.AltQueue.tail)->nextext = (struct dsym *)sym;
                    ModuleInfo.g.AltQueue.tail = (struct dsym *)sym;
                }
#endif
            }
        }
    }
    return( NOT_ERROR );
}
示例#23
0
ret_code ExterndefDirective( int i, struct asm_tok tokenarray[] )
/***************************************************************/
{
    char                *token;
#if MANGLERSUPP
    char                *mangle_type = NULL;
#endif
    struct asym         *sym;
    enum lang_type      langtype;
    char isnew;
    struct qualified_type ti;

    DebugMsg1(("ExterndefDirective(%u) enter\n", i));

    i++; /* skip EXTERNDEF token */
#if MANGLERSUPP
    mangle_type = Check4Mangler( &i, tokenarray );
#endif
    do {

        ti.Ofssize = ModuleInfo.Ofssize;

        /* get the symbol language type if present */
        langtype = ModuleInfo.langtype;
        GetLangType( &i, tokenarray, &langtype );

        /* get the symbol name */
        if( tokenarray[i].token != T_ID ) {
            return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
        }
        token = tokenarray[i++].string_ptr;

        /* go past the colon */
        if( tokenarray[i].token != T_COLON ) {
            return( EmitError( COLON_EXPECTED ) );
        }
        i++;
        sym = SymSearch( token );

        //typetoken = tokenarray[i].string_ptr;
        ti.mem_type = MT_EMPTY;
        ti.size = 0;
        ti.is_ptr = 0;
        ti.is_far = FALSE;
        ti.ptr_memtype = MT_EMPTY;
        ti.symtype = NULL;
        ti.Ofssize = ModuleInfo.Ofssize;

        if ( tokenarray[i].token == T_ID && ( 0 == _stricmp( tokenarray[i].string_ptr, "ABS" ) ) ) {
            /* v2.07: MT_ABS is obsolete */
            //ti.mem_type = MT_ABS;
            i++;
        } else if ( tokenarray[i].token == T_DIRECTIVE && tokenarray[i].tokval == T_PROTO ) {
            /* dont scan this line further!
             * CreateProto() will either define a SYM_EXTERNAL or fail
             * if there's a syntax error or symbol redefinition.
             */
            sym = CreateProto( i + 1, tokenarray, token, langtype );
#if 0 /* global queue is obsolete */
            if ( sym && sym->isglobal == FALSE ) {
                sym->isglobal = TRUE;
                QAddItem( &ModuleInfo.g.GlobalQueue, sym );
            }
#endif
            return( sym ? NOT_ERROR : ERROR );
        } else if ( tokenarray[i].token != T_FINAL && tokenarray[i].token != T_COMMA ) {
            if ( GetQualifiedType( &i, tokenarray, &ti ) == ERROR )
                return( ERROR );
        }

        isnew = FALSE;
        if ( sym == NULL || sym->state == SYM_UNDEFINED ) {
            sym = CreateExternal( sym, token, TRUE );
            isnew = TRUE;
        }

        /* new symbol? */

        if ( isnew ) {
            DebugMsg1(("ExterndefDirective(%s): memtype=%X set, ofssize=%X\n", token, ti.mem_type, ti.Ofssize ));

            /* v2.05: added to accept type prototypes */
            if ( ti.is_ptr == 0 && ti.symtype && ti.symtype->isproc ) {
                CreateProc( sym, NULL, SYM_EXTERNAL );
                CopyPrototype( (struct dsym *)sym, (struct dsym *)ti.symtype );
                ti.mem_type = ti.symtype->mem_type;
                ti.symtype = NULL;
            }
            switch ( ti.mem_type ) {
            //case MT_ABS:
            case MT_EMPTY:
                /* v2.04: hack no longer necessary */
                //if ( sym->weak == TRUE )
                //    sym->equate = TRUE; /* allow redefinition by EQU, = */
                break;
            case MT_FAR:
                /* v2.04: don't inherit current segment for FAR externals
                 * if -Zg is set.
                 */
                if ( Options.masm_compat_gencode )
                    break; 
                /* fall through */
            default:
                //SetSymSegOfs( sym );
                sym->segment = &CurrSeg->sym;
            }
            sym->Ofssize = ti.Ofssize;

            if ( ti.is_ptr == 0 && ti.Ofssize != ModuleInfo.Ofssize ) {
                sym->seg_ofssize = ti.Ofssize;
                if ( sym->segment && ((struct dsym *)sym->segment)->e.seginfo->Ofssize != sym->seg_ofssize )
                    sym->segment = NULL;
            }

            sym->mem_type = ti.mem_type;
            sym->is_ptr = ti.is_ptr;
            sym->isfar = ti.is_far;
            sym->ptr_memtype = ti.ptr_memtype;
            if ( ti.mem_type == MT_TYPE )
                sym->type = ti.symtype;
            else
                sym->target_type = ti.symtype;

            /* v2.04: only set language if there was no previous definition */
            SetMangler( sym, langtype, mangle_type );

        } else if ( Parse_Pass == PASS_1 ) {

            /* v2.05: added to accept type prototypes */
            if ( ti.is_ptr == 0 && ti.symtype && ti.symtype->isproc ) {
                ti.mem_type = ti.symtype->mem_type;
                ti.symtype = NULL;
            }
            /* ensure that the type of the symbol won't change */

            if ( sym->mem_type != ti.mem_type ) {
                /* if the symbol is already defined (as SYM_INTERNAL), Masm
                 won't display an error. The other way, first externdef and
                 then the definition, will make Masm complain, however */
                DebugMsg(("ExterndefDirective: type conflict for %s. mem_types old-new: %X-%X\n", sym->name, sym->mem_type, ti.mem_type));
                EmitWarn( 1, SYMBOL_TYPE_CONFLICT, sym->name );
            } else if ( sym->mem_type == MT_TYPE && sym->type != ti.symtype ) {
                struct asym *sym2 = sym;
                /* skip alias types and compare the base types */
                DebugMsg(("ExterndefDirective(%s): types differ: %X (%s) - %X (%s)\n", sym->name, sym->type, sym->type->name, ti.symtype, ti.symtype->name));
                while ( sym2->type )
                    sym2 = sym2->type;
                while ( ti.symtype->type )
                    ti.symtype = ti.symtype->type;
                if ( sym2 != ti.symtype ) {
                    DebugMsg(("ExterndefDirective(%s): type conflict old-new: %X (%s) - %X (%s)\n", sym->name, sym2, sym2->name, ti.symtype, ti.symtype->name));
                    EmitWarn( 1, SYMBOL_TYPE_CONFLICT, sym->name );
                }
            }

            /* v2.04: emit a - weak - warning if language differs.
             * Masm doesn't warn.
             */
            if ( langtype != LANG_NONE && sym->langtype != langtype )
                EmitWarn( 3, LANGUAGE_ATTRIBUTE_CONFLICT, sym->name );
        }
        sym->isdefined = TRUE;

#if 0
        /* write a global entry if none has been written yet */
        if ( sym->state == SYM_EXTERNAL && sym->weak == FALSE )
            ;/* skip EXTERNDEF if a real EXTERN/COMM was done */
        else if ( sym->isglobal == FALSE ) {
            sym->isglobal = TRUE;
            DebugMsg1(("ExterndefDirective(%s): writing a global entry\n", sym->name));
            QAddItem( &ModuleInfo.g.GlobalQueue, sym );
        }
#else
        if ( sym->state == SYM_INTERNAL && sym->ispublic == FALSE ) {
            sym->ispublic = TRUE;
            AddPublicData( sym );
        }
#endif

        if ( tokenarray[i].token != T_FINAL )
            if ( tokenarray[i].token == T_COMMA ) {
                if ( (i + 1) < Token_Count )
                    i++;
            } else {
                return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) );
            }

    } while ( i < Token_Count );

    return( NOT_ERROR );
}
示例#24
0
ret_code SetCPU( enum cpu_info newcpu )
/*************************************/
{
    int temp;

    DebugMsg1(("SetCPU(%X) enter\n", newcpu ));
    if ( newcpu == P_86 || ( newcpu & P_CPU_MASK ) ) {
        /* reset CPU and EXT bits */
        ModuleInfo.curr_cpu &= ~( P_CPU_MASK | P_EXT_MASK | P_PM );

        /* set CPU bits */
        ModuleInfo.curr_cpu |= newcpu & ( P_CPU_MASK | P_PM );

        /* set default FPU bits if nothing is given and .NO87 not active */
        if ( (ModuleInfo.curr_cpu & P_FPU_MASK) != P_NO87 &&
            ( newcpu & P_FPU_MASK ) == 0 ) {
            ModuleInfo.curr_cpu &= ~P_FPU_MASK;
            if ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_286 )
                ModuleInfo.curr_cpu |= P_87;
            else if ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_386 )
                ModuleInfo.curr_cpu |= P_287;
            else
                ModuleInfo.curr_cpu |= P_387;
        }

    }
    if( newcpu & P_FPU_MASK ) {
        ModuleInfo.curr_cpu &= ~P_FPU_MASK;
        ModuleInfo.curr_cpu |= (newcpu & P_FPU_MASK);
    }
#if AMD64_SUPPORT
    /* enable MMX, K3D, SSEx for 64bit cpus */
    if ( ( newcpu & P_CPU_MASK ) == P_64 )
        ModuleInfo.curr_cpu |= P_EXT_ALL;
#endif
    if( newcpu & P_EXT_MASK ) {
        ModuleInfo.curr_cpu &= ~P_EXT_MASK;
        ModuleInfo.curr_cpu |= (newcpu & P_EXT_MASK);
    }

    /* set the Masm compatible @Cpu value */

    temp = ModuleInfo.curr_cpu & P_CPU_MASK;
    switch ( temp ) {
    case P_186: ModuleInfo.cpu = M_8086 | M_186; break;
    case P_286: ModuleInfo.cpu = M_8086 | M_186 | M_286; break;
    case P_386: ModuleInfo.cpu = M_8086 | M_186 | M_286 | M_386; break;
    case P_486: ModuleInfo.cpu = M_8086 | M_186 | M_286 | M_386 | M_486; break;
    case P_586: ModuleInfo.cpu = M_8086 | M_186 | M_286 | M_386 | M_486 | M_586; break;
    /* Masm's .686 directive doesn't set the Pentium flag! A bug? */
    //case P_686: ModuleInfo.cpu = M_8086 | M_186 | M_286 | M_386 | M_486 | M_586 | M_686; break;
#if AMD64_SUPPORT
    case P_64:
#endif
    case P_686: ModuleInfo.cpu = M_8086 | M_186 | M_286 | M_386 | M_486 | M_686; break;
    default: ModuleInfo.cpu = M_8086; break;
    }
    if ( ModuleInfo.curr_cpu & P_PM )
        ModuleInfo.cpu = ModuleInfo.cpu | M_PROT;

    temp = ModuleInfo.curr_cpu & P_FPU_MASK;
    switch (temp) {
    case P_87:  ModuleInfo.cpu = ModuleInfo.cpu | M_8087;     break;
    case P_287: ModuleInfo.cpu = ModuleInfo.cpu | M_8087 | M_287; break;
    case P_387: ModuleInfo.cpu = ModuleInfo.cpu | M_8087 | M_287 | M_387; break;
    }

    DebugMsg1(("SetCPU: ModuleInfo.curr_cpu=%X, @Cpu=%X\n", ModuleInfo.curr_cpu, ModuleInfo.cpu ));

    //MakeCPUConstant( newcpu );
    if ( ModuleInfo.model == MODEL_NONE )
#if AMD64_SUPPORT
        if ( ( ModuleInfo.curr_cpu & P_CPU_MASK) >= P_64 ) {
            SetDefaultOfssize( USE64 );
        } else
#endif
            SetDefaultOfssize( ((ModuleInfo.curr_cpu & P_CPU_MASK) >= P_386) ? USE32 : USE16 );

    /* Set @Cpu */
    /* differs from Codeinfo cpu setting */

    sym_Cpu = CreateVariable( "@Cpu", ModuleInfo.cpu );

    return( NOT_ERROR );
}
示例#25
0
void AddPublicData( struct asym *sym )
/************************************/
{
    DebugMsg1(("AddPublicData(%s)\n", sym->name ));
    QAddItem( &ModuleInfo.g.PubQueue, sym );
}
示例#26
0
void LstWrite( enum lsttype type, uint_32 oldofs, void *value )
/*************************************************************/
{
    uint_32 newofs;
    struct asym *sym = value;
    int     len;
    int     len2;
    int     idx;
    int     srcfile;
    char    *p1;
    char    *p2;
    char    *pSrcline;
    struct lstleft *pll;
    struct lstleft ll;
    //char    buffer2[MAX_LINE_LEN]; /* stores text macro value */

    if ( ModuleInfo.list == FALSE || CurrFile[LST] == NULL || ( ModuleInfo.line_flags & LOF_LISTED ) )
        return;
    if ( ModuleInfo.GeneratedCode && ( ModuleInfo.list_generated_code == FALSE ) )
        return;
    if ( MacroLevel ) {
        switch ( ModuleInfo.list_macro ) {
        case LM_NOLISTMACRO:
            return;
        case LM_LISTMACRO:
            /* todo: filter certain macro lines */
            break;
        }
    }

    ModuleInfo.line_flags |= LOF_LISTED;

    DebugMsg1(("LstWrite( %u, %" I32_SPEC "u ): enter [ pos=%" I32_SPEC "u, GeneratedCode=%u, MacroLevel=%u ]\n", type, oldofs, list_pos, ModuleInfo.GeneratedCode, MacroLevel ));
    pSrcline = CurrSource;
#if FASTPASS
    if ( ( Parse_Pass > PASS_1 ) && UseSavedState ) {
        if ( ModuleInfo.GeneratedCode == 0 ) {
            if ( !( ModuleInfo.line_flags & LOF_SKIPPOS ) )
                list_pos = LineStoreCurr->list_pos;
#if USELSLINE /* either use CurrSource + CurrComment or LineStoreCurr->line (see assemble.c, OnePass() */
            pSrcline = LineStoreCurr->line;
            if ( ModuleInfo.CurrComment ) { /* if comment was removed, readd it! */
                *( LineStoreCurr->line + strlen( LineStoreCurr->line ) ) = ';';
                ModuleInfo.CurrComment = NULL;
            }
#endif
            DebugMsg1(("LstWrite: Pass=%u, stored pos=%" I32_SPEC "u\n", Parse_Pass+1, list_pos ));
        }
        fseek( CurrFile[LST], list_pos, SEEK_SET );
    }
#endif

    ll.next = NULL;
    memset( ll.buffer, ' ', sizeof( ll.buffer ) );
    srcfile = get_curr_srcfile();

    switch ( type ) {
    case LSTTYPE_DATA:
        if ( Parse_Pass == PASS_1 && Options.first_pass_listing == FALSE ) {
            break;
        }
        /* no break */
    case LSTTYPE_CODE:
        newofs = GetCurrOffset();
        sprintf( ll.buffer, "%08" I32_SPEC "X", oldofs );
        ll.buffer[OFSSIZE] = ' ';

        if ( CurrSeg == NULL )
            break;
        //if ( write_to_file == FALSE )
        if ( Options.first_pass_listing ) {
            if ( Parse_Pass > PASS_1 )
                break;
#ifdef DEBUG_OUT
        } else if ( Options.max_passes == 1 ) {
            ; /* write a listing in pass 1 */
#endif
        } else if ( Parse_Pass == PASS_1 )  /* changed v1.96 */
            break;

        len = CODEBYTES;
        p2 = ll.buffer + OFSSIZE + 2;

        if ( CurrSeg->e.seginfo->CodeBuffer == NULL ||
            CurrSeg->e.seginfo->written == FALSE ) {
            while ( oldofs < newofs && len ) {
                *p2++ = '0';
                *p2++ = '0';
                oldofs++;
                len--;
            }
            break;
        }

        /* OMF hold just a small buffer for one LEDATA record */
        /* if it has been flushed, use LastCodeBufSize */
        idx = (CurrSeg->e.seginfo->current_loc - CurrSeg->e.seginfo->start_loc)
            - (newofs - oldofs);
        if ( Options.output_format == OFORMAT_OMF ) {
            /* v2.11: additional check to make the hack more robust [ test case:  db 800000h dup (0) ] */
            if ( ( idx+LastCodeBufSize ) < 0 )
                break; /* just exit. The code bytes area will remain empty */
            while ( idx < 0 && len ) {
                sprintf( p2, "%02X", CurrSeg->e.seginfo->CodeBuffer[idx+LastCodeBufSize] );
                p2 += 2;
                idx++;
                oldofs++;
                len--;
            }
        } else if (idx < 0)
            idx = 0;

        while ( oldofs < newofs && len ) {
            sprintf( p2, "%02X", CurrSeg->e.seginfo->CodeBuffer[idx] );
            p2 += 2;
            idx++;
            oldofs++;
            len--;
        }
        *p2 = ' ';
        break;
    case LSTTYPE_EQUATE:
        /* v2.10: display current offset if equate is an alias for a label in this segment */
        idx = 1;
        if ( sym->segment && sym->segment == &CurrSeg->sym ) {
            sprintf( ll.buffer, "%08" I32_SPEC "X", GetCurrOffset() );
            idx = 10;
        }
        ll.buffer[idx] = '=';
#if AMD64_SUPPORT
        if ( sym->value3264 != 0 && ( sym->value3264 != -1 || sym->value >= 0 ) )
            sprintf( &ll.buffer[idx+2], "%-" PREFFMTSTR I64_SPEC "X", (uint_64)sym->value + ( (uint_64)sym->value3264 << 32 ) );
        else
#endif
            sprintf( &ll.buffer[idx+2], "%-" PREFFMTSTR I32_SPEC "X", sym->value );
        ll.buffer[28] = ' ';
        break;
    case LSTTYPE_TMACRO:
        ll.buffer[1] = '=';
        //GetLiteralValue( buffer2, sym->string_ptr );
        //strcpy( buffer2, sym->string_ptr );
        for ( p1 = sym->string_ptr, p2 = &ll.buffer[3], pll = &ll; *p1; ) {
            if ( p2 >= &pll->buffer[28] ) {
                struct lstleft *next = myalloca( sizeof( struct lstleft ) );
                pll->next = next;
                pll = next;
                pll->next = NULL;
                memset( pll->buffer, ' ', sizeof( pll->buffer) );
                p2 = &pll->buffer[3];
            }
            *p2++ = *p1++;
        }
        break;
    case LSTTYPE_MACROLINE:
        ll.buffer[1] = '>';
        pSrcline = value;
        break;
    case LSTTYPE_LABEL:
        oldofs = GetCurrOffset();
        /* no break */
    case LSTTYPE_STRUCT:
        sprintf( ll.buffer, "%08" I32_SPEC "X", oldofs );
        ll.buffer[8] = ' ';
        break;
    case LSTTYPE_DIRECTIVE:
        if ( CurrSeg || value ) {
            sprintf( ll.buffer, "%08" I32_SPEC "X", oldofs );
            ll.buffer[8] = ' ';
        }
        break;
    default: /* LSTTYPE_MACRO */
        if ( *pSrcline == NULLC && ModuleInfo.CurrComment == NULL && srcfile == ModuleInfo.srcfile ) {
            DebugMsg1(("LstWrite: type=%u, writing CRLF\n", type ));
            fwrite( NLSTR, 1, NLSIZ, CurrFile[LST] );
            list_pos += NLSIZ;
            return;
        }
        break;
    }

#if FASTPASS
    if ( Parse_Pass == PASS_1 || UseSavedState == FALSE ) {
#endif
        idx = sizeof( ll.buffer );
        if ( ModuleInfo.GeneratedCode )
            ll.buffer[28] = '*';
        if ( MacroLevel ) {
            len = sprintf( &ll.buffer[29], "%u", MacroLevel );
            ll.buffer[29+len] = ' ';
        }
        if ( srcfile != ModuleInfo.srcfile ) {
            ll.buffer[30] = 'C';
        }
#ifdef DEBUG_OUT
        ll.last = NULLC;
#endif
#if FASTPASS
    } else {
        idx = OFSSIZE + 2 + 2 * CODEBYTES;
#ifdef DEBUG_OUT
        ll.buffer[idx] = NULLC;
#endif
    }
#endif
    fwrite( ll.buffer, 1, idx, CurrFile[LST] );

    len = strlen( pSrcline );
    len2 = ( ModuleInfo.CurrComment ? strlen( ModuleInfo.CurrComment ) : 0 );

    list_pos += sizeof( ll.buffer ) + len + len2 + NLSIZ;
    DebugMsg1(("LstWrite: writing (%u b) >%s< [%u/%u], new pos=%" I32_SPEC "u\n", idx, ll.buffer, len, len2, list_pos ));

    /* write source and comment part */
#if FASTPASS
    if ( Parse_Pass == PASS_1 || UseSavedState == FALSE ) {
#endif
        if ( len )
            fwrite( pSrcline, 1, len, CurrFile[LST] );
        if ( len2 ) {
            fwrite( ModuleInfo.CurrComment, 1, len2, CurrFile[LST] );
            DebugMsg1(("LstWrite: writing (%u b) >%s%s<\n", len + len2 + NLSIZ, pSrcline, ModuleInfo.CurrComment ));
        }
#ifdef DEBUG_OUT
        else DebugMsg1(("LstWrite: writing (%u b) >%s<\n", len + NLSIZ, pSrcline ));
#endif
        fwrite( NLSTR, 1, NLSIZ, CurrFile[LST] );
#if FASTPASS
    }
#endif

    /* write optional additional lines.
     * currently works in pass one only.
     */
    for ( pll = ll.next; pll; pll = pll->next ) {
        fwrite( pll->buffer, 1, 32, CurrFile[LST] );
        fwrite( NLSTR, 1, NLSIZ, CurrFile[LST] );
        list_pos += 32 + NLSIZ;
        DebugMsg1(("LstWrite: additional line >%s<, new pos=%" I32_SPEC "u\n", pll->buffer, list_pos ));
    }
    return;
}
示例#27
0
ret_code PublicDirective( int i, struct asm_tok tokenarray[] )
/************************************************************/
{
#if MANGLERSUPP
    char                *mangle_type = NULL;
#endif
    char                *token;
    struct asym         *sym;
    //struct dsym       *dir;
    char                skipitem;
    enum lang_type      langtype;

    DebugMsg1(("PublicDirective(%u) enter\n", i));
    i++; /* skip PUBLIC directive */
#if MANGLERSUPP
    mangle_type = Check4Mangler( &i, tokenarray );
#endif
    do {

        /* read the optional language type */
        langtype = ModuleInfo.langtype;
        GetLangType( &i, tokenarray, &langtype );

        if ( tokenarray[i].token != T_ID ) {
            return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
        }
        /* get the symbol name */
        token = tokenarray[i++].string_ptr;

        DebugMsg1(("PublicDirective: sym=%s\n", token ));

        /* Add the public name */
        sym = SymSearch( token );
        if ( Parse_Pass == PASS_1 ) {
            if ( sym == NULL ) {
                if ( sym = SymCreate( token ) ) {
                    sym_add_table( &SymTables[TAB_UNDEF], (struct dsym *)sym );
                    DebugMsg1(("PublicDirective(%s): new symbol\n", sym->name ));
                } else
                    return( ERROR ); /* name was too long */
            }
            skipitem = FALSE;
        } else {
            if ( sym == NULL || sym->state == SYM_UNDEFINED ) {
                EmitErr( SYMBOL_NOT_DEFINED, token );
                //return( ERROR ); /* v2.04: dont exit */
            }
        }
        if ( sym ) {
            switch ( sym->state ) {
            case SYM_UNDEFINED:
                break;
            case SYM_INTERNAL:
                if ( sym->scoped == TRUE ) {
                    EmitErr( CANNOT_DECLARE_SCOPED_CODE_LABEL_AS_PUBLIC, sym->name );
                    skipitem = TRUE;
                    //return( ERROR );
                }
                break;
            case SYM_EXTERNAL:
                if ( sym->iscomm == TRUE ) {
                    EmitErr( CANNOT_DEFINE_AS_PUBLIC_OR_EXTERNAL, sym->name );
                    skipitem = TRUE;
                    //return( ERROR );
                } else if ( sym->weak == FALSE ) {
                    /* for EXTERNs, emit a different error msg */
                    EmitErr( SYMBOL_REDEFINITION, sym->name );
                    skipitem = TRUE;
                    //return( ERROR );
                }
                break;
            default:
                EmitErr( CANNOT_DEFINE_AS_PUBLIC_OR_EXTERNAL, sym->name );
                skipitem = TRUE;
                //return( ERROR );
            }
            if( Parse_Pass == PASS_1 && skipitem == FALSE ) {
                if ( sym->ispublic == FALSE ) {
                    sym->ispublic = TRUE;
                    AddPublicData( sym ); /* put it into the public table */
                }
                SetMangler( sym, langtype, mangle_type );
            }
        }

        if ( tokenarray[i].token != T_FINAL )
            if ( tokenarray[i].token == T_COMMA ) {
                if ( (i + 1) < Token_Count )
                    i++;
            } else {
                return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ) );
            }

    } while ( i < Token_Count );

    return( NOT_ERROR );
}
示例#28
0
/* set memory model, called by ModelDirective()
 * also set predefined symbols:
 * - @CodeSize  (numeric)
 * - @code      (text)
 * - @DataSize  (numeric)
 * - @data      (text)
 * - @stack     (text)
 * - @Model     (numeric)
 * - @Interface (numeric)
 * inactive:
 * - @fardata   (text)
 * - @fardata?  (text)
 * Win64 only:
 * - @ReservedStack (numeric)
 */
static void SetModel( void )
/**************************/
{
    int         value;
    const char  *textvalue;
    //struct asym     *sym;

    DebugMsg1(("SetModel() enter (model=%u)\n", ModuleInfo.model ));
    /* if model is set, it disables OT_SEGMENT of -Zm switch */
    if ( ModuleInfo.model == MODEL_FLAT ) {
        ModuleInfo.offsettype = OT_FLAT;
#if AMD64_SUPPORT
        SetDefaultOfssize( ((ModuleInfo.curr_cpu & P_CPU_MASK) >= P_64 ) ? USE64 : USE32 );
#else
        SetDefaultOfssize( USE32 );
#endif
    } else
        ModuleInfo.offsettype = OT_GROUP;

    NewLineQueue();
    ModelSimSegmInit( ModuleInfo.model ); /* create segments in first pass */
    ModelAssumeInit();

    if ( ModuleInfo.list )
        LstWriteSrcLine();

    RunLineQueue();

    if ( Parse_Pass != PASS_1 )
        return;

    /* Set @CodeSize */
    if ( SIZE_CODEPTR & ( 1 << ModuleInfo.model ) ) {
        value = 1;
        /* v2.06: SimpleType[] is obsolete */
        //SimpleType[ST_PROC].mem_type = MT_FAR;
    } else {
        value = 0;
        // SimpleType[ST_PROC].mem_type = MT_NEAR; /* this is default */
    }
    sym_CodeSize = AddPredefinedConstant( "@CodeSize", value );
    AddPredefinedText( "@code", SimGetSegName( SIM_CODE ) );

    /* Set @DataSize */
    switch( ModuleInfo.model ) {
    case MODEL_COMPACT:
    case MODEL_LARGE:
        value = 1;
        break;
    case MODEL_HUGE:
        value = 2;
        break;
    default:
        value = 0;
        break;
    }
    sym_DataSize = AddPredefinedConstant( "@DataSize", value );

    textvalue = ( ModuleInfo.model == MODEL_FLAT ? "FLAT" : szDgroup );
    AddPredefinedText( "@data", textvalue );

    if ( ModuleInfo.distance == STACK_FAR )
        textvalue = "STACK";
    AddPredefinedText( "@stack", textvalue );

#if 0
    AddPredefinedText( "@fardata", ( ModuleInfo.model == MODEL_FLAT ? "FLAT" : SimGetSegName( SIM_FARDATA ) ) );
    AddPredefinedText( "@fardata?", ( ModuleInfo.model == MODEL_FLAT ? "FLAT" : SimGetSegName( SIM_FARDATA_UN ) ) );
#endif

    /* Set @Model and @Interface */

    sym_Model     = AddPredefinedConstant( "@Model", ModuleInfo.model );
    sym_Interface = AddPredefinedConstant( "@Interface", ModuleInfo.langtype );

#if AMD64_SUPPORT
    if ( ModuleInfo.defOfssize == USE64 && ModuleInfo.fctype == FCT_WIN64 ) {
        ReservedStack.mem_type = MT_EMPTY;
        ReservedStack.state = SYM_INTERNAL;
        ReservedStack.isdefined = TRUE;
        ReservedStack.predefined = TRUE;
#if FASTMEM==0
        ReservedStack.staticmem = TRUE;
#endif
        ReservedStack.variable = TRUE;
        ReservedStack.name_size = 14; /* sizeof( "@ReservedStack" ) */
        SymAddGlobal( &ReservedStack );
    }
#endif
}
示例#29
0
/* PreprocessLine() is the "preprocessor".
 * 1. the line is tokenized with Tokenize(), Token_Count set
 * 2. (text) macros are expanded by ExpandLine()
 * 3. "preprocessor" directives are executed
 */
int PreprocessLine( char *line, struct asm_tok tokenarray[] )
/***********************************************************/
{
    int i;

    /* v2.11: GetTextLine() removed - this is now done in ProcessFile() */

    /* v2.08: moved here from GetTextLine() */
    ModuleInfo.CurrComment = NULL;
    /* v2.06: moved here from Tokenize() */
    ModuleInfo.line_flags = 0;
    /* Token_Count is the number of tokens scanned */
    Token_Count = Tokenize( line, 0, tokenarray, TOK_DEFAULT );

#ifdef DEBUG_OUT
    cntppl0++;
    if ( ModuleInfo.GeneratedCode )
        DebugMsg1(("PreprocessLine: >%s<\n", line ));
    else
        DebugMsg1(("PreprocessLine(%s): >%s< cmt=%s\n", GetTopSrcName(), line, ModuleInfo.CurrComment ? ModuleInfo.CurrComment : "" ));
#endif

#if REMOVECOMENT == 0
    if ( Token_Count == 0 && ( CurrIfState == BLOCK_ACTIVE || ModuleInfo.listif ) )
        LstWriteSrcLine();
#endif

    if ( Token_Count == 0 )
        return( 0 );

#ifdef DEBUG_OUT
    /* option -np, skip preprocessor? */
    if ( Options.skip_preprocessor )
        return( Token_Count );
#endif

    /* CurrIfState != BLOCK_ACTIVE && Token_Count == 1 | 3 may happen
     * if a conditional assembly directive has been detected by Tokenize().
     * However, it's important NOT to expand then */
    if ( CurrIfState == BLOCK_ACTIVE ) {
        if ( ( tokenarray[Token_Count].bytval & TF3_EXPANSION ? ExpandText( line, tokenarray, TRUE ) : ExpandLine( line, tokenarray ) ) < NOT_ERROR )
            return( 0 );
    }

    DebugCmd( cntppl1++ );

    i = 0;
    if ( Token_Count > 2 && ( tokenarray[1].token == T_COLON || tokenarray[1].token == T_DBL_COLON ) )
        i = 2;

    /* handle "preprocessor" directives:
     * IF, ELSE, ENDIF, ...
     * FOR, REPEAT, WHILE, ...
     * PURGE
     * INCLUDE
     * since v2.05, error directives are no longer handled here!
     */
    if ( tokenarray[i].token == T_DIRECTIVE &&
        tokenarray[i].dirtype <= DRT_INCLUDE ) {

        /* if i != 0, then a code label is located before the directive */
        if ( i > 1 ) {
            if ( ERROR == WriteCodeLabel( line, tokenarray ) )
                return( 0 );
        }
        directive_tab[tokenarray[i].dirtype]( i, tokenarray );
        return( 0 );
    }

    /* handle preprocessor directives which need a label */

    if ( tokenarray[0].token == T_ID && tokenarray[1].token == T_DIRECTIVE ) {
        struct asym *sym;
        switch ( tokenarray[1].dirtype ) {
        case DRT_EQU:
            /*
             * EQU is a special case:
             * If an EQU directive defines a text equate
             * it MUST be handled HERE and 0 must be returned to the caller.
             * This will prevent further processing, nothing will be stored
             * if FASTPASS is on.
             * Since one cannot decide whether EQU defines a text equate or
             * a number before it has scanned its argument, we'll have to
             * handle it in ANY case and if it defines a number, the line
             * must be stored and, if -EP is set, written to stdout.
             */
            if ( sym = CreateConstant( tokenarray ) ) {
                if ( sym->state != SYM_TMACRO ) {
#if FASTPASS
                    if ( StoreState ) FStoreLine( 0 );
#endif
                    if ( Options.preprocessor_stdout == TRUE )
                        WritePreprocessedLine( line );
                }
                /* v2.03: LstWrite() must be called AFTER StoreLine()! */
                if ( ModuleInfo.list == TRUE ) {
                    LstWrite( sym->state == SYM_INTERNAL ? LSTTYPE_EQUATE : LSTTYPE_TMACRO, 0, sym );
                }
            }
            return( 0 );
        case DRT_MACRO:
        case DRT_CATSTR: /* CATSTR + TEXTEQU directives */
        case DRT_SUBSTR:
            directive_tab[tokenarray[1].dirtype]( 1, tokenarray );
            return( 0 );
        }
    }

    DebugCmd( cntppl2++ );
    return( Token_Count );
}
示例#30
0
/* handle .model directive
 * syntax: .MODEL <FLAT|TINY|SMALL...> [,<C|PASCAL|STDCALL...>][,<NEARSTACK|FARSTACK>][,<OS_DOS|OS_OS2>]
 * sets fields
 * - ModuleInfo.model
 * - ModuleInfo.language
 * - ModuleInfo.distance
 * - ModuleInfo.ostype
 * if model is FLAT, defines FLAT pseudo-group
 * set default segment names for code and data
 */
ret_code ModelDirective( int i, struct asm_tok tokenarray[] )
/***********************************************************/
{
    enum model_type model;
    enum lang_type language;
    enum dist_type distance;
    enum os_type ostype;
    int index;
    uint_8 init;
    uint_8 initv;

    DebugMsg1(("ModelDirective enter\n"));
    /* v2.03: it may occur that "code" is defined BEFORE the MODEL
     * directive (i.e. DB directives in AT-segments). For FASTPASS,
     * this may have caused errors because contents of the ModuleInfo
     * structure was saved before the .MODEL directive.
     */
    //if( Parse_Pass != PASS_1 ) {
    if( Parse_Pass != PASS_1 && ModuleInfo.model != MODEL_NONE ) {
        /* just set the model with SetModel() if pass is != 1.
         * This won't set the language ( which can be modified by
         * OPTION LANGUAGE directive ), but the language in ModuleInfo
         * isn't needed anymore once pass one is done.
         */
        SetModel();
        return( NOT_ERROR );
    }

    i++;
    if ( tokenarray[i].token == T_FINAL ) {
        EmitError( EXPECTED_MEMORY_MODEL );
        return( ERROR );
    }
    /* get the model argument */
    index = FindToken( tokenarray[i].string_ptr, ModelToken, sizeof( ModelToken )/sizeof( ModelToken[0] ) );
    if( index >= 0 ) {
        if( ModuleInfo.model != MODEL_NONE ) {
            EmitWarn( 2, MODEL_DECLARED_ALREADY );
            return( NOT_ERROR );
        }
        model = index + 1;
        i++;
    } else {
        EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
        return( ERROR );
    }

    /* get the optional arguments: language, stack distance, os */
    init = 0;
    while ( i < ( Token_Count - 1 ) && tokenarray[i].token == T_COMMA ) {
        i++;
        if ( tokenarray[i].token != T_COMMA ) {
            if ( GetLangType( &i, tokenarray, &language ) == NOT_ERROR ) {
                initv = INIT_LANG;
            } else {
                index = FindToken( tokenarray[i].string_ptr, ModelAttr, sizeof( ModelAttr )/sizeof( ModelAttr[0] ) );
                if ( index < 0 )
                    break;
                initv = ModelAttrValue[index].init;
                switch ( initv ) {
                case INIT_STACK:
                    if ( model == MODEL_FLAT ) {
                        EmitError( INVALID_MODEL_PARAM_FOR_FLAT );
                        return( ERROR );
                    }
                    distance = ModelAttrValue[index].value;
                    break;
                case INIT_OS:
                    ostype = ModelAttrValue[index].value;
                    break;
                }
                i++;
            }
            /* attribute set already? */
            if ( initv & init ) {
                i--;
                break;
            }
            init |= initv;
        }
    }
    /* everything parsed successfully? */
    if ( tokenarray[i].token != T_FINAL ) {
        EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos );
        return( ERROR );
    }

    if ( model == MODEL_FLAT ) {
        if ( ( ModuleInfo.curr_cpu & P_CPU_MASK) < P_386 ) {
            EmitError( INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE );
            return( ERROR );
        }
        DefineFlatGroup();
    }

    ModuleInfo.model = model;
    if ( init & INIT_LANG ) {
        ModuleInfo.langtype = language;
#if AMD64_SUPPORT
        /* v2.03: set header and fastcall type to win64 if x64 is active.
         * This is rather hackish, but currently there's no other possibility
         * to enable the win64 ABI from the source.
         */
        if ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) == P_64 )
            if ( language == LANG_FASTCALL &&
                model == MODEL_FLAT &&
                Options.output_format != OFORMAT_ELF ) {
                DebugMsg(("ModelDirective: FASTCALL type set to WIN64\n"));
                ModuleInfo.header_format = HFORMAT_WIN64;
                ModuleInfo.fctype = FCT_WIN64;
            }
#endif
    }
    if ( init & INIT_STACK )
        ModuleInfo.distance = distance;
    if ( init & INIT_OS )
        ModuleInfo.ostype = ostype;

    SetModelDefaultSegNames();
    SetModel();

    return( NOT_ERROR );
}