Exemplo n.º 1
0
void SetModelDefaultSegNames( void )
/**********************************/
{
    /* init segment names with default values */
    memcpy( SegmNames, SegmNamesDef, sizeof(SegmNames) );

    /* option -nt set? */
    if( Options.names[OPTN_TEXT_SEG] ) {
        SegmNames[SIM_CODE] = LclAlloc( strlen( Options.names[OPTN_TEXT_SEG] ) + 1 );
        strcpy( SegmNames[SIM_CODE], Options.names[OPTN_TEXT_SEG] );
    } else {
        if ( SIZE_CODEPTR & ( 1 << ModuleInfo.model ) ) {
            /* for some models, the code segment contains the module name */
            SegmNames[SIM_CODE] = LclAlloc( strlen( SegmNamesDef[SIM_CODE] ) + strlen( ModuleInfo.name ) + 1 );
            strcpy( SegmNames[SIM_CODE], ModuleInfo.name );
            strcat( SegmNames[SIM_CODE], SegmNamesDef[SIM_CODE] );
        }
    }

    /* option -nd set? */
    if ( Options.names[OPTN_DATA_SEG] ) {
        SegmNames[SIM_DATA] = LclAlloc( strlen( Options.names[OPTN_DATA_SEG] ) + 1 );
        strcpy( SegmNames[SIM_DATA], Options.names[OPTN_DATA_SEG] );
    }
    return;
}
Exemplo n.º 2
0
static struct dsym *CreateSegment( struct dsym *seg, const char *name, bool add_global )
/**************************************************************************************/
{
    if ( seg == NULL )
        seg = ( add_global ? (struct dsym *)SymCreate( name ) : (struct dsym *)SymAlloc( name ) );
    else if ( seg->sym.state == SYM_UNDEFINED )
        sym_remove_table( &SymTables[TAB_UNDEF], seg );

    if ( seg ) {
        seg->sym.state = SYM_SEG;
        seg->e.seginfo = LclAlloc( sizeof( struct seg_info ) );
        memset( seg->e.seginfo, 0, sizeof( struct seg_info ) );
        seg->e.seginfo->Ofssize = ModuleInfo.defOfssize;
        seg->e.seginfo->alignment = 4; /* this is PARA (2^4) */
        seg->e.seginfo->combine = COMB_INVALID;
        /* null class name, in case none is mentioned */
        seg->e.seginfo->class_name_idx = 1;
        seg->next = NULL;
        /* don't use sym_add_table(). Thus the "prev" member
         * becomes free for another use.
         */
        if ( SymTables[TAB_SEG].head == NULL )
            SymTables[TAB_SEG].head = SymTables[TAB_SEG].tail = seg;
        else {
            SymTables[TAB_SEG].tail->next = seg;
            SymTables[TAB_SEG].tail = seg;
        }
    }
    return( seg );
}
Exemplo n.º 3
0
static struct dsym *CreateGroup( const char *name )
/*************************************************/
{
    struct dsym    *grp;

    grp = (struct dsym *)SymSearch( name );

    if( grp == NULL || grp->sym.state == SYM_UNDEFINED ) {
        if ( grp == NULL )
            grp = (struct dsym *)SymCreate( name );
        else
            sym_remove_table( &SymTables[TAB_UNDEF], grp );

        grp->sym.state = SYM_GRP;
        grp->e.grpinfo = LclAlloc( sizeof( struct grp_info ) );
        grp->e.grpinfo->seglist = NULL;
        //grp->e.grpinfo->grp_idx = 0;
        //grp->e.grpinfo->lname_idx = 0;
        grp->e.grpinfo->numseg = 0;
        sym_add_table( &SymTables[TAB_GRP], grp );

        grp->sym.list = TRUE;
        grp->e.grpinfo->grp_idx = ++grpdefidx;
        grp->e.grpinfo->lname_idx = ++LnamesIdx;
        AddLnameData( &grp->sym );
    } else if( grp->sym.state != SYM_GRP ) {
        EmitErr( SYMBOL_REDEFINITION, name );
        return( NULL );
    }
    grp->sym.isdefined = TRUE;
    return( grp );
}
Exemplo n.º 4
0
Arquivo: input.c Projeto: JWasm/JWasm
void InputInit( void )
/********************/
{
    struct src_item *fl;
#if 0
    char        path[FILENAME_MAX];
    char        drive[_MAX_DRIVE];
    char        dir[_MAX_DIR];
#endif

    DebugMsg(( "InputInit() enter\n" ));
    //ModuleInfo.g.cnt_fnames = 0;
    //ModuleInfo.g.FNames = NULL;
    //IncludePath = NULL;
    //src_stack = NULL;
    SrcFree = NULL; /* v2.11 */
#if FILESEQ
    FileSeq.head = NULL;
#endif
#ifdef DEBUG_OUT
    cntppl0 = 0;
    cntppl1 = 0;
    cntppl2 = 0;
    cnttok0 = 0;
    cnttok1 = 0;
    cntflines = 0;
    cntlines = 0;
#endif

    /* add path of main module to the include path.
     * v2.12: unnecessary since v2.10, since the directory part of the
     * current source is added if a file is to be included; see SearchFile().
     */
    //_splitpath( CurrFName[ASM], drive, dir, NULL, NULL );
    //if ( drive[0] || dir[0] ) {
    //    _makepath( path, drive, dir, NULL, NULL );
    //    AddStringToIncludePath( path );
    //}

    srclinebuffer = LclAlloc( SIZE_SRCLINES + SIZE_TOKENARRAY + SIZE_STRINGBUFFER );
    /* the comment buffer is at the end of the source line buffer */
    commentbuffer = srclinebuffer + SIZE_SRCLINES - MAX_LINE_LEN;
    /* behind the comment buffer is the token buffer */
    ModuleInfo.tokenarray = (struct asm_tok *)( srclinebuffer + SIZE_SRCLINES );
    token_stringbuf = srclinebuffer + SIZE_SRCLINES + SIZE_TOKENARRAY;
#ifdef DEBUG_OUT
    end_tokenarray = (struct asm_tok *)token_stringbuf;
    end_stringbuf = token_stringbuf + SIZE_STRINGBUFFER;
    DebugMsg(( "InputInit: srclinebuffer=%p, tokenarray=%p, token_stringbuf=%p end_stringbuf=%p\n", srclinebuffer, ModuleInfo.tokenarray, token_stringbuf, end_stringbuf ));
#endif

    fl = PushSrcItem( SIT_FILE, CurrFile[ASM] );
    fl->srcfile = ModuleInfo.srcfile = AddFile( CurrFName[ASM] );
    /* setting a function pointer won't work for text macros! */
    //FileCur->sfunc_ptr = &GetFileCur;
    FileCur->string_ptr = GetFName( fl->srcfile )->fname;

    DebugMsg(( "InputInit() exit\n" ));
}
Exemplo n.º 5
0
Arquivo: input.c Projeto: JWasm/JWasm
void AddFileSeq( unsigned file )
/******************************/
{
    struct file_seq *node;
    node = LclAlloc( sizeof( struct file_seq ) );
    node->next = NULL;
    node->file = file;
    if ( FileSeq.head == NULL )
        FileSeq.head = FileSeq.tail = node;
    else {
        ((struct file_seq *)FileSeq.tail)->next = node;
        FileSeq.tail = node;
    }
}
Exemplo n.º 6
0
Arquivo: input.c Projeto: JWasm/JWasm
/* push a new item onto the source stack.
 * type: SIT_FILE or SIT_MACRO
 */
static struct src_item *PushSrcItem( char type, void *pv )
/********************************************************/
{
    struct src_item   *curr;

    if ( SrcFree ) {
        curr = SrcFree;
        SrcFree = curr->next;
    } else
        curr = LclAlloc( sizeof( struct src_item ) );
    curr->next = src_stack;
    src_stack = curr;
    curr->type = type;
    curr->content = pv;
    curr->line_num = 0;
    return( curr );
}
Exemplo n.º 7
0
static uint_8 *checkflush( struct dsym *seg, uint_8 *buffer, uint_8 *curr, int size )
/***********************************************************************************/
{
#if COFF_SUPPORT
    uint_8 *p;
#endif

    if ( ( curr - buffer ) && ( ( curr - buffer ) + size ) > ( 1024 - 8 ) ) {
        switch ( Options.output_format ) {
#if COFF_SUPPORT
        case OFORMAT_COFF:
            p = LclAlloc( (curr - buffer) + sizeof( struct qditem ) );
            ((struct qditem *)p)->next = NULL;
            ((struct qditem *)p)->size = curr - buffer;
            memcpy( p + sizeof( struct qditem ), buffer, curr - buffer );
            if ( seg->sym.name[7] == 'S' ) {  /* .debug$S or .debug$T ? */
                if ( DebugS.head == NULL )
                    DebugS.head = DebugS.tail = p;
                else {
                    ((struct qditem *)(DebugS.tail))->next = p;
                    DebugS.tail = p;
                }
            } else {
                if ( DebugT.head == NULL )
                    DebugT.head = DebugT.tail = p;
                else {
                    ((struct qditem *)(DebugT.tail))->next = p;
                    DebugT.tail = p;
                }
            }
            seg->e.seginfo->current_loc = seg->e.seginfo->start_loc + ( curr - buffer );
            seg->e.seginfo->start_loc = seg->e.seginfo->current_loc;
            break;
#endif
        case OFORMAT_OMF:
            seg->e.seginfo->current_loc = seg->e.seginfo->start_loc + ( curr - buffer );
            omf_write_ledata( seg );
            break;
        }
        return( buffer );
    }
    return( curr );
}
Exemplo n.º 8
0
Arquivo: input.c Projeto: 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 );
}
Exemplo n.º 9
0
Arquivo: linnum.c Projeto: JWasm/JWasm
static void AddLinnumData( struct line_num_info *data )
/*****************************************************/
{
    struct qdesc *q;
#if COFF_SUPPORT
    if ( Options.output_format == OFORMAT_COFF ) {
        q = (struct qdesc *)CurrSeg->e.seginfo->LinnumQueue;
        if ( q == NULL ) {
            q = LclAlloc( sizeof( struct qdesc ) );
            CurrSeg->e.seginfo->LinnumQueue = q;
            q->head = NULL;
        }
    } else
#endif
        q = &LinnumQueue;

    data->next = NULL;
    if ( q->head == NULL)
        q->head = q->tail = data;
    else {
        ((struct line_num_info *)q->tail)->next = data;
        q->tail = data;
    }
}
Exemplo n.º 10
0
/*
 * used by EQU if the value to be assigned to a symbol is text.
 * - sym:   text macro name, may be NULL
 * - name:  identifer ( if sym == NULL )
 * - value: value of text macro ( original line, BEFORE expansion )
 */
struct asym *SetTextMacro( struct asm_tok tokenarray[], struct asym *sym, const char *name, const char *value )
/*************************************************************************************************************/
{
    int count;
    //char *p;

    DebugCmd( equcnt++ );

    if ( sym == NULL )
        sym = SymCreate( name );
    else if ( sym->state == SYM_UNDEFINED ) {
        sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym );
#if FASTPASS
        /* the text macro was referenced before being defined.
         * this is valid usage, but it requires a full second pass.
         * just simply deactivate the fastpass feature for this module!
         */
        SkipSavedState();
#endif
        EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name );
    } else if ( sym->state != SYM_TMACRO ) {
        EmitErr( SYMBOL_REDEFINITION, name );
        return( NULL );
    }

    sym->state = SYM_TMACRO;
    sym->isdefined = TRUE;

    if ( tokenarray[2].token == T_STRING && tokenarray[2].string_delim == '<' ) {

        /* the simplest case: value is a literal. define a text macro! */
        /* just ONE literal is allowed */
        if ( tokenarray[3].token != T_FINAL ) {
            EmitErr( SYNTAX_ERROR_EX, tokenarray[3].tokpos );
            return( NULL );
        }
        value = tokenarray[2].string_ptr;
        count = tokenarray[2].stringlen;
    } else {
        /*
         * the original source is used, since the tokenizer has
         * deleted some information.
         */
        //while ( isspace( *value ) ) value++; /* probably obsolete */
        count = strlen( value );
        /* skip trailing spaces */
        for ( ; count; count-- )
            if ( isspace( *( value + count - 1 ) ) == FALSE )
                break;
    }
#if FASTMEM==0
    if ( sym->string_ptr )
        LclFree( sym->string_ptr );
    sym->string_ptr = (char *)LclAlloc( count + 1 );
#else
    if ( sym->total_size < ( count + 1 ) ) {
        LclFree( sym->string_ptr ); /* is a noop if fastmem is on */
        sym->string_ptr = (char *)LclAlloc( count + 1 );
        sym->total_size = count + 1;
    }
#endif
    memcpy( sym->string_ptr, value, count );
    *(sym->string_ptr + count) = NULLC;

    DebugMsg1(( "SetTextMacro(%s): value is >%s<, exit\n", sym->name, sym->string_ptr ));
    return( sym );
}
Exemplo n.º 11
0
ret_code GrpDir( int i, struct asm_tok tokenarray[] )
/***************************************************/
{
    char        *name;
    struct dsym *grp;
    struct dsym *seg;

    /* GROUP directive must be at pos 1, needs a name at pos 0 */
    if( i != 1 ) {
        EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
        return( ERROR );
    }
#if COFF_SUPPORT || ELF_SUPPORT
    /* GROUP valid for OMF + BIN only */
    if ( Options.output_format == OFORMAT_COFF
#if ELF_SUPPORT
        || Options.output_format == OFORMAT_ELF
#endif
       ) {
        EmitError( GROUP_DIRECTIVE_INVALID_FOR_COFF );
        return( ERROR );
    }
#endif
    grp = CreateGroup( tokenarray[0].string_ptr );
    if( grp == NULL )
        return( ERROR );

    i++; /* go past GROUP */

    do {

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

        seg = (struct dsym *)SymSearch( name );
        if ( Parse_Pass == PASS_1 ) {
            if( seg == NULL || seg->sym.state == SYM_UNDEFINED ) {
                seg = CreateSegment( seg, name, TRUE );
                /* inherit the offset magnitude from the group */
                if ( grp->e.grpinfo->seglist )
                    seg->e.seginfo->Ofssize = grp->sym.Ofssize;
            } else if( seg->sym.state != SYM_SEG ) {
                EmitErr( SEGMENT_EXPECTED, name );
                return( ERROR );
            } else if( seg->e.seginfo->group != NULL &&
                       seg->e.seginfo->group != &grp->sym ) {
                /* segment is in another group */
                DebugMsg(("GrpDir: segment >%s< is in group >%s< already\n", name, seg->e.seginfo->group->name));
                EmitErr( SEGMENT_IN_ANOTHER_GROUP, name );
                return( ERROR );
            }
            /* the first segment will define the group's word size */
            if( grp->e.grpinfo->seglist == NULL ) {
                grp->sym.Ofssize = seg->e.seginfo->Ofssize;
            } else if ( grp->sym.Ofssize != seg->e.seginfo->Ofssize ) {
                EmitErr( GROUP_SEGMENT_SIZE_CONFLICT, grp->sym.name, seg->sym.name );
                return( ERROR );
            }
        } else {
            /* v2.04: don't check the "defined" flag. It's for IFDEF only! */
            //if( seg == NULL || seg->sym.state != SYM_SEG || seg->sym.defined == FALSE ) {
            /* v2.07: check the "segment" field instead of "defined" flag! */
            //if( seg == NULL || seg->sym.state != SYM_SEG ) {
            if( seg == NULL || seg->sym.state != SYM_SEG || seg->sym.segment == NULL ) {
                EmitErr( SEG_NOT_DEFINED, name );
                return( ERROR );
            }
        }

        /* insert segment in group if it's not there already */
        if ( seg->e.seginfo->group == NULL ) {
            struct seg_item    *si;

            /* set the segment's grp */
            seg->e.seginfo->group = &grp->sym;

            si = LclAlloc( sizeof( struct seg_item ) );
            si->seg = seg;
            si->next = NULL;
            grp->e.grpinfo->numseg++;

            /* insert the segment at the end of linked list */
            if( grp->e.grpinfo->seglist == NULL ) {
                grp->e.grpinfo->seglist = si;
            } else {
                struct seg_item *curr;
                curr = grp->e.grpinfo->seglist;
                while( curr->next != NULL ) {
                    curr = curr->next;
                }
                curr->next = si;
            }
        }

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

    } while ( i < Token_Count );

    return( NOT_ERROR );
}
Exemplo n.º 12
0
void SegmentInit( int pass )
/**************************/
{
    struct dsym *curr;
    uint_32     i;
#ifdef __I86__
    char __huge *p;
#else
    char        *p;
#endif
    //struct fixup *fix;

    DebugMsg(("SegmentInit(%u) enter\n", pass ));
    CurrSeg      = NULL;
    stkindex     = 0;

    if ( pass == PASS_1 ) {
        grpdefidx   = 0;
        LnamesIdx   = 1; /* the first Lname is a null-string */
        //pCodeBuff = NULL;
        buffer_size = 0;
        //flat_grp    = NULL;

        symPC.sfunc_ptr = &SetCurPC;
        symPC.mem_type = MT_NEAR;
        symPC.state = SYM_INTERNAL;
        symPC.isdefined = TRUE;
        symPC.predefined = TRUE;
        symPC.variable = TRUE; /* added v1.96. Important for fixup creation */
#if FASTMEM==0
        symPC.staticmem = TRUE;
#endif
        symPC.name_size = 1; /* sizeof("$") */
        symPC.list = FALSE; /* don't display the '$' symbol in symbol list */
        SymAddGlobal( &symPC );

#if 0 /* v2.03: obsolete, also belongs to simplified segment handling */
        /* set ModuleInfo.code_class */
        if( Options.code_class  )
            size = strlen( Options.code_class ) + 1;
        else
            size = 4 + 1;
        ModuleInfo.code_class = LclAlloc( size );
        if ( Options.code_class )
            strcpy( ModuleInfo.code_class, Options.code_class );
        else
            strcpy( ModuleInfo.code_class, "CODE" );
#endif
    }

    /*
     * alloc a buffer for the contents
     */

    if ( ModuleInfo.pCodeBuff == NULL && Options.output_format != OFORMAT_OMF ) {
        for( curr = SymTables[TAB_SEG].head, buffer_size = 0; curr; curr = curr->next ) {
            /* v2.04: can't happen */
            //if( ( curr->sym.state != SYM_SEG ) || ( curr->sym.segment == NULL ) )
            //    continue;
            if ( curr->e.seginfo->bytes_written ) {
                i = curr->sym.max_offset - curr->e.seginfo->start_loc;
                /* the segment can grow in step 2-n due to forward references.
                 * for a quick solution just add 25% to the size if segment
                 * is a code segment. (v2.02: previously if was added only if
                 * code segment contained labels, but this isn't sufficient.)
                 */
                //if ( curr->e.seginfo->labels ) /* v2.02: changed */
                if ( curr->e.seginfo->segtype == SEGTYPE_CODE )
                    i = i + (i >> 2);
                DebugMsg(("SegmentInit(%u), %s: max_ofs=%" FX32 ", alloc_size=%" FX32 "h\n", pass, curr->sym.name, curr->sym.max_offset, i ));
                buffer_size += i;
            }
        }
        if ( buffer_size ) {
            ModuleInfo.pCodeBuff = LclAlloc( buffer_size );
            DebugMsg(("SegmentInit(%u): total buffer size=%" FX32 ", start=%p\n", pass, buffer_size, ModuleInfo.pCodeBuff ));
        }
    }
Exemplo n.º 13
0
/* string macro initialization
 * this proc is called once per module
 */
void StringInit( void )
/*********************/
{
    int i;
    struct dsym *macro;

    DebugMsg(( "StringInit() enter\n" ));

#ifdef DEBUG_OUT
    catstrcnt = 0;
    substrcnt = 0;
    sizstrcnt = 0;
    instrcnt = 0;
    equcnt = 0;
#endif

    /* add @CatStr() macro func */

    macro = CreateMacro( "@CatStr" );
    macro->sym.isdefined = TRUE;
    macro->sym.predefined = TRUE;
    macro->sym.func_ptr = CatStrFunc;
    macro->sym.isfunc = TRUE;
    /* v2.08: @CatStr() changed to VARARG */
    macro->sym.mac_vararg = TRUE;
    macro->e.macroinfo->parmcnt = 1;
    macro->e.macroinfo->parmlist = LclAlloc( sizeof( struct mparm_list ) * 1 );
    macro->e.macroinfo->parmlist[0].deflt = NULL;
    macro->e.macroinfo->parmlist[0].required = FALSE;

    /* add @InStr() macro func */

    macro = CreateMacro( "@InStr" );
    macro->sym.isdefined = TRUE;
    macro->sym.predefined = TRUE;
    macro->sym.func_ptr = InStrFunc;
    macro->sym.isfunc = TRUE;
    macro->e.macroinfo->parmcnt = 3;
    macro->e.macroinfo->autoexp = 1; /* param 1 (pos) is expanded */
    macro->e.macroinfo->parmlist = LclAlloc(sizeof( struct mparm_list) * 3);
    for (i = 0; i < 3; i++) {
        macro->e.macroinfo->parmlist[i].deflt = NULL;
        //macro->e.macroinfo->parmlist[i].label = parmnames[i];
        macro->e.macroinfo->parmlist[i].required = (i != 0);
    }

    /* add @SizeStr() macro func */

    macro = CreateMacro( "@SizeStr" );
    macro->sym.isdefined = TRUE;
    macro->sym.predefined = TRUE;
    macro->sym.func_ptr = SizeStrFunc;
    macro->sym.isfunc = TRUE;
    macro->e.macroinfo->parmcnt = 1;
    macro->e.macroinfo->parmlist = LclAlloc(sizeof( struct mparm_list));
    macro->e.macroinfo->parmlist[0].deflt = NULL;
    //macro->e.macroinfo->parmlist[0].label = parmnames[0];
    /* macro->e.macroinfo->parmlist[0].required = TRUE; */
    /* the string parameter is NOT required, '@SizeStr()' is valid */
    macro->e.macroinfo->parmlist[0].required = FALSE;

    /* add @SubStr() macro func */

    macro = CreateMacro( "@SubStr" );
    macro->sym.isdefined = TRUE;
    macro->sym.predefined = TRUE;
    macro->sym.func_ptr = SubStrFunc;
    macro->sym.isfunc = TRUE;
    macro->e.macroinfo->parmcnt = 3;
    macro->e.macroinfo->autoexp = 2 + 4; /* param 2 (pos) and 3 (size) are expanded */
    macro->e.macroinfo->parmlist = LclAlloc(sizeof( struct mparm_list) * 3);
    for (i = 0; i < 3; i++) {
        macro->e.macroinfo->parmlist[i].deflt = NULL;
        //macro->e.macroinfo->parmlist[i].label = parmnames[i];
        macro->e.macroinfo->parmlist[i].required = (i < 2);
    }

    return;
}
Exemplo n.º 14
0
ret_code CatStrDir( int i, struct asm_tok tokenarray[] )
/******************************************************/
{
    struct asym *sym;
    int count;
    char *p;
    /* struct expr opndx; */

    DebugMsg1(("CatStrDir(%u) enter\n", i ));
    DebugCmd( catstrcnt++ );

#if 0 /* can't happen */
    /* syntax must be <id> CATSTR textitem[,textitem,...] */
    if ( i != 1 ) {
        return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
    }
    if ( tokenarray[0].token != T_ID ) {
        return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) );
    }
#endif
    i++; /* go past CATSTR/TEXTEQU */

    /* v2.08: don't copy to temp buffer */
    //*StringBufferEnd = NULLC;
    /* check correct syntax and length of items */
    for ( count = 0; i < Token_Count; ) {
        DebugMsg1(("CatStrDir(%s): item[%u]=%s delim=0x%x\n", tokenarray[0].string_ptr, i, tokenarray[i].string_ptr, tokenarray[i].string_delim ));
        if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) {
            DebugMsg(("CatStrDir: error, not a <>-literal: %s\n", tokenarray[i].tokpos ));
            return( TextItemError( &tokenarray[i] ) );
        }
        /* v2.08: using tokenarray.stringlen is not quite correct, since some chars
         * are stored in 2 bytes (!) */
        if ( ( count + tokenarray[i].stringlen ) >= MAX_LINE_LEN ) {
            DebugMsg(("CatStrDir: error, literal too long: %u + %u >= %u\n", count, tokenarray[i].stringlen, MAX_LINE_LEN ));
            return( EmitError( STRING_OR_TEXT_LITERAL_TOO_LONG ) );
        }
        /* v2.08: don't copy to temp buffer */
        //strcpy( StringBufferEnd + count, tokenarray[i].string_ptr );
        count = count + tokenarray[i].stringlen;
        i++;
        if ( ( tokenarray[i].token != T_COMMA ) &&
            ( tokenarray[i].token != T_FINAL ) ) {
            return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
        }
        i++;
    }

    sym = SymSearch( tokenarray[0].string_ptr );
    if ( sym == NULL ) {
        sym = SymCreate( tokenarray[0].string_ptr );
        DebugMsg1(( "CatStrDir: new symbol %s created\n", sym->name));
    } else if( sym->state == SYM_UNDEFINED ) {
        /* v2.01: symbol has been used already. Using
         * a textmacro before it has been defined is
         * somewhat problematic.
         */
        sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym );
#if FASTPASS
        SkipSavedState(); /* further passes must be FULL! */
#endif
        EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name );
    } else if( sym->state != SYM_TMACRO ) {
        /* it is defined as something else, get out */
        DebugMsg(( "CatStrDir(%s) exit, symbol redefinition\n", sym->name));
        return( EmitErr( SYMBOL_REDEFINITION, sym->name ) );
    }


    sym->state = SYM_TMACRO;
    sym->isdefined = TRUE;
#if FASTMEM==0
    if ( sym->string_ptr )
        LclFree( sym->string_ptr );
    sym->string_ptr = (char *)LclAlloc( count + 1 );
#else
    /* v2.08: reuse string space if fastmem is on */
    if ( sym->total_size < ( count+1 ) ) {
        LclFree( sym->string_ptr ); /* is a noop if fastmem is on */
        sym->string_ptr = (char *)LclAlloc( count + 1 );
        sym->total_size = count + 1;
    }
#endif
    /* v2.08: don't use temp buffer */
    //memcpy( sym->string_ptr, StringBufferEnd, count + 1 );
    for ( i = 2, p = sym->string_ptr; i < Token_Count; i += 2 ) {
        memcpy( p, tokenarray[i].string_ptr, tokenarray[i].stringlen );
        p += tokenarray[i].stringlen;
    }
    *p = NULLC;
    DebugMsg1(("CatStrDir(%s) (new) value: >%s<\n", sym->name, sym->string_ptr ));

    if ( ModuleInfo.list )
        LstWrite( LSTTYPE_TMACRO, 0, sym );

    return( NOT_ERROR );
}
Exemplo n.º 15
0
/* SubStr()
 * defines a text equate.
 * syntax: name SUBSTR <string>, pos [, size]
 */
ret_code SubStrDir( int i, struct asm_tok tokenarray[] )
/******************************************************/
{
    struct asym         *sym;
    char                *name;
    char                *p;
    //char                *newvalue;
    int                 pos;
    int                 size;
    int                 cnt;
    bool                chksize;
    struct expr         opndx;

    DebugMsg1(("SubStrDir enter\n"));
    DebugCmd( substrcnt++ );

    /* at least 5 items are needed
     * 0  1      2      3 4    5   6
     * ID SUBSTR SRC_ID , POS [, LENGTH]
     */
#if 0 /* can't happen */
    if ( i != 1 ) {
        return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
    }
    if ( tokenarray[0].token != T_ID ) {
        return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) );
    }
#endif
    name = tokenarray[0].string_ptr;

    i++; /* go past SUBSTR */

    /* third item must be a string */

    if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) {
        DebugMsg(("SubStrDir: error, no text item\n"));
        return( TextItemError( &tokenarray[i] ) );
    }
    p = tokenarray[i].string_ptr;
    cnt = tokenarray[i].stringlen;

    i++;
    DebugMsg1(("SubStrDir(%s): src=>%s<\n", name, p));

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

    /* get pos, must be a numeric value and > 0 */
    /* v2.11: flag NOUNDEF added - no forward ref possible */

    if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) {
        DebugMsg(("SubStrDir(%s): invalid pos value\n", name));
        return( ERROR );
    }

    /* v2.04: "string" constant allowed as second argument */
    //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) {
    if ( opndx.kind != EXPR_CONST ) {
        DebugMsg(("SubStrDir(%s): pos value is not a constant\n", name));
        return( EmitError( CONSTANT_EXPECTED ) );
    }

    /* pos is expected to be 1-based */
    pos = opndx.value;
    if ( pos <= 0 ) {
        return( EmitError( POSITIVE_VALUE_EXPECTED ) );
    }
    if ( tokenarray[i].token != T_FINAL ) {
        if ( tokenarray[i].token != T_COMMA ) {
            return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) );
        }
        i++;
        /* get size, must be a constant */
        /* v2.11: flag NOUNDEF added - no forward ref possible */
        if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) {
            DebugMsg(("SubStrDir(%s): invalid size value\n", name));
            return( ERROR );
        }
        /* v2.04: string constant ok */
        //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) {
        if ( opndx.kind != EXPR_CONST ) {
            DebugMsg(("SubStrDir(%s): size value is not a constant\n", name));
            return( EmitError( CONSTANT_EXPECTED ) );
        }
        size = opndx.value;
        if ( tokenarray[i].token != T_FINAL ) {
            DebugMsg(("SubStrDir(%s): additional items found\n", name));
            return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
        }
        if ( size < 0 ) {
            return( EmitError( COUNT_MUST_BE_POSITIVE_OR_ZERO ) );
        }
        chksize = TRUE;
    } else {
        size = -1;
        chksize = FALSE;
    }
#if 0
    cnt = pos;
    /* position p to start of substring */
    for ( pos--; pos > 0 && *p ; pos--, p++ )
        if ( *p == '!' && *(p+1) != NULLC )
            p++;
    if ( *p == NULLC ) {
        return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, cnt ) );
    }
    if ( *p == '!' && *(p+1) != NULLC )
        p++;
    for ( newvalue = p, cnt = size; *p && cnt; cnt--, p++ )
        if ( *p == '!' && *(p+1) != NULLC )
            p++;
    /* v2.04: check added */
    if ( chksize && cnt ) {
        return( EmitError( COUNT_VALUE_TOO_LARGE ) );
    }
    size = p - newvalue;
    p = newvalue;
#else
    if ( pos > cnt ) {
        return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) );
    }
    if ( chksize && (pos+size-1) > cnt )  {
        return( EmitError( COUNT_VALUE_TOO_LARGE ) );
    }
    p += pos - 1;
    if ( size == -1 )
        size = cnt - pos + 1;
#endif

    sym = SymSearch( name );

    /* if we've never seen it before, put it in */
    if( sym == NULL ) {
        sym = SymCreate( name );
    } else if( sym->state == SYM_UNDEFINED ) {
        /* it was referenced before being defined. This is
         * a bad idea for preprocessor text items, because it
         * will require a full second pass!
         */
        sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym );
#if FASTPASS
        SkipSavedState();
        EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name );
#endif
    } else if( sym->state != SYM_TMACRO ) {
        /* it is defined as something incompatible, get out */
        DebugMsg(( "SubStrDir(%s) error, incompatible type\n", sym->name));
        return( EmitErr( SYMBOL_REDEFINITION, sym->name ) );
    }

    sym->state = SYM_TMACRO;
    sym->isdefined = TRUE;

#if FASTMEM==0
    if ( sym->string_ptr )
        LclFree( sym->string_ptr );
    sym->string_ptr = (char *)LclAlloc( size + 1 );
#else
    if ( sym->total_size < ( size + 1 ) ) {
        LclFree( sym->string_ptr );
        sym->string_ptr = LclAlloc ( size + 1 );
        sym->total_size = size + 1;
    }
#endif
    memcpy( sym->string_ptr, p, size );
    *(sym->string_ptr + size) = NULLC;
    DebugMsg1(("SubStrDir(%s): result=>%s<\n", sym->name, sym->string_ptr ));

    LstWrite( LSTTYPE_TMACRO, 0, sym );

    return( NOT_ERROR );
}
Exemplo n.º 16
0
Arquivo: linnum.c Projeto: JWasm/JWasm
void AddLinnumDataRef( unsigned srcfile, uint_32 line_num )
/*********************************************************/
{
    struct line_num_info    *curr;

#if COFF_SUPPORT
    /* COFF line number info is related to functions/procedures. Since
     * assembly allows code lines outside of procs, "dummy" procs must
     * be generated. A dummy proc lasts until
     * - a true PROC is detected or
     * - the source file changes or
     * - the segment/section changes ( added in v2.11 )
     */
    if ( Options.output_format == OFORMAT_COFF &&
        CurrProc == NULL &&
        ( dmyproc == NULL ||
        dmyproc->debuginfo->file != srcfile ||
        dmyproc->segment != (struct asym *)CurrSeg ) ) {
        char procname[12];
        if ( dmyproc ) {
            /**/myassert( dmyproc->segment );
            dmyproc->total_size =
                ((struct dsym *)dmyproc->segment)->e.seginfo->current_loc -
                dmyproc->offset;
        }
        sprintf( procname, "$$$%05u", procidx );
        DebugMsg1(("AddLinnumDataRef(src=%u.%u): CurrProc==NULL, dmyproc=%s searching proc=%s\n", srcfile, line_num, dmyproc ? dmyproc->name : "NULL", procname ));
        dmyproc = SymSearch( procname );

        /* in pass 1, create the proc */
        if ( dmyproc == NULL ) {
            dmyproc = CreateProc( NULL, procname, SYM_INTERNAL );
            DebugMsg1(("AddLinnumDataRef: new proc %s created\n", procname ));
            dmyproc->isproc = TRUE; /* flag is usually set inside ParseProc() */
            dmyproc->included = TRUE;
            AddPublicData( dmyproc );
        } else
            procidx++; /* for passes > 1, adjust procidx */

        /* if the symbols isn't a PROC, the symbol name has been used
         * by the user - bad! A warning should be displayed */
        if ( dmyproc->isproc == TRUE ) {
            SetSymSegOfs( dmyproc );
            dmyproc->Ofssize = ModuleInfo.Ofssize;
            dmyproc->langtype = ModuleInfo.langtype;
            if ( write_to_file == TRUE ) {
                curr = LclAlloc( sizeof( struct line_num_info ) );
                curr->sym = dmyproc;
                curr->line_number = GetLineNumber();
                curr->file = srcfile;
                curr->number = 0;
                DebugMsg1(("AddLinnumDataRef: CURRPROC=NULL, sym=%s, calling AddLinnumData(src=%u.%u)\n", curr->sym->name, curr->file, curr->line_number ));
                AddLinnumData( curr );
            }
        }
    }
#endif

    if(  line_num && ( write_to_file == FALSE || lastLineNumber == line_num )) {
#ifdef DEBUG_OUT
        if ( write_to_file == TRUE )
            DebugMsg1(("AddLinnumDataRef(src=%u.%u) line skipped, lastline=%u\n", srcfile, line_num, lastLineNumber ));
#endif
        return;
    }
    DebugMsg1(("AddLinnumDataRef(src=%u.%u): currofs=%Xh, CurrProc=%s, GeneratedCode=%u\n", srcfile, line_num, GetCurrOffset(), CurrProc ? CurrProc->sym.name : "NULL", ModuleInfo.GeneratedCode ));

    curr = LclAlloc( sizeof( struct line_num_info ) );
    curr->number = line_num;
#if COFF_SUPPORT
    if ( line_num == 0 ) { /* happens for COFF only */
        /* changed v2.03 (CurrProc might have been NULL) */
        /* if ( Options.output_format == OFORMAT_COFF && CurrProc->sym.public == FALSE ) { */
        /* v2.09: avoid duplicates, check for pass 1 */
        //if ( Options.output_format == OFORMAT_COFF && CurrProc && CurrProc->sym.public == FALSE ) {
        if ( Parse_Pass == PASS_1 &&
            Options.output_format == OFORMAT_COFF && CurrProc && CurrProc->sym.ispublic == FALSE ) {
            CurrProc->sym.included = TRUE;
            AddPublicData( (struct asym *)CurrProc );
        }
        /* changed v2.03 */
        /* curr->sym = (struct asym *)CurrProc; */
        curr->sym = ( CurrProc ? (struct asym *)CurrProc : dmyproc );
        curr->line_number = GetLineNumber();
        curr->file        = srcfile;
        /* set the function's size! */
        if ( dmyproc ) {
            /**/myassert( dmyproc->segment );
            dmyproc->total_size =
                ((struct dsym *)dmyproc->segment)->e.seginfo->current_loc -
                dmyproc->offset;
            dmyproc = NULL;
        }
        /* v2.11: write a 0x7fff line item if prologue exists */
        if ( CurrProc && CurrProc->e.procinfo->size_prolog ) {
            DebugMsg1(("AddLinnumDataRef: calling AddLinnumData(src=%u.%u) sym=%s\n", curr->file, curr->line_number, curr->sym->name ));
            AddLinnumData( curr );
            curr = LclAlloc( sizeof( struct line_num_info ) );
            curr->number = GetLineNumber();
            curr->offset = GetCurrOffset();
            curr->srcfile = srcfile;
        }
    } else {
#endif
        curr->offset = GetCurrOffset();
        curr->srcfile = srcfile;
#if COFF_SUPPORT
    }
#endif
    lastLineNumber = line_num;

    /* v2.11: added, improved multi source support for CV.
     * Also, the size of line number info could have become > 1024,
     * ( even > 4096, thus causing an "internal error in omfint.c" )
     */
    if ( Options.output_format == OFORMAT_OMF )
        omf_check_flush( curr );

    /* v2.10: warning if line-numbers for segments without class code! */
    if ( CurrSeg->e.seginfo->linnum_init == FALSE ) {
        CurrSeg->e.seginfo->linnum_init = TRUE;
        if ( TypeFromClassName( CurrSeg, CurrSeg->e.seginfo->clsym ) != SEGTYPE_CODE ) {
            EmitWarn( 2, LINNUM_INFO_FOR_SEGMENT_WITHOUT_CLASS_CODE, CurrSeg->sym.name );
        }
    }
    DebugMsg1(("AddLinnumDataRef: calling AddLinnumData(src=%u.%u ofs=%X)\n", curr->number == 0 ? curr->file : curr->srcfile, curr->number, curr->offset ));
    AddLinnumData( curr );

    return;
}
Exemplo n.º 17
0
ret_code SafeSEHDirective( int i, struct asm_tok tokenarray[] )
/*************************************************************/
{
    struct asym    *sym;
    struct qnode   *node;

    if ( Options.output_format != OFORMAT_COFF ) {
        if ( Parse_Pass == PASS_1)
            EmitWarn( 2, DIRECTIVE_IGNORED_WITHOUT_X, "coff" );
        return( NOT_ERROR );
    }
    if ( Options.safeseh == FALSE ) {
        if ( Parse_Pass == PASS_1)
            EmitWarn( 2, DIRECTIVE_IGNORED_WITHOUT_X, "safeseh" );
        return( NOT_ERROR );
    }
    i++;
    if ( tokenarray[i].token != T_ID ) {
        return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
    }
    sym = SymSearch( tokenarray[i].string_ptr );

    /* make sure the argument is a true PROC */
    if ( sym == NULL || sym->state == SYM_UNDEFINED ) {
        if ( Parse_Pass != PASS_1 ) {
            return( EmitErr( SYMBOL_NOT_DEFINED, tokenarray[i].string_ptr ) );
        }
    } else if ( sym->isproc == FALSE ) {
        return( EmitErr( SAFESEH_ARGUMENT_MUST_BE_A_PROC, tokenarray[i].string_ptr ) );
    }

    if ( Parse_Pass == PASS_1 ) {
        if ( sym ) {
            for ( node = ModuleInfo.g.SafeSEHQueue.head; node; node = node->next )
                if ( node->elmt == sym )
                    break;
        } else {
            sym = SymCreate( tokenarray[i].string_ptr );
            node = NULL;
        }
        if ( node == NULL ) {
            sym->used = TRUE; /* make sure an external reference will become strong */
#if 0 /* v2.11: use QAddItem() */
            node = LclAlloc( sizeof( struct qnode ) );
            node->elmt = sym;
            node->next = NULL;
            if ( ModuleInfo.g.SafeSEHQueue.head == 0 )
                ModuleInfo.g.SafeSEHQueue.head = ModuleInfo.g.SafeSEHQueue.tail = node;
            else {
                ((struct qnode *)ModuleInfo.g.SafeSEHQueue.tail)->next = node;
                ModuleInfo.g.SafeSEHQueue.tail = node;
            }
#else
            QAddItem( &ModuleInfo.g.SafeSEHQueue, sym );
#endif
        }
    }
    i++;
    if ( tokenarray[i].token != T_FINAL ) {
        return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) );
    }

    return( NOT_ERROR );
}
Exemplo n.º 18
0
ret_code SegmentDir( int i, struct asm_tok tokenarray[] )
/*******************************************************/
{
    char                is_old;
    char                *token;
    int                 typeidx;
    const struct typeinfo *type;          /* type of option */
    int                 temp;
    int                 temp2;
    uint                initstate = 0;  /* flags for attribute initialization */
    unsigned char       oldreadonly;    /* readonly value of a defined segment */
    //unsigned char       oldsegtype;
    unsigned char       oldOfssize;
    char                oldalign;
    char                oldcombine;
    uint                oldclassidx;
    uint_8              oldcharacteristics;
    struct dsym         *dir;
    char                *name;
    struct asym         *sym;
    struct expr         opndx;

    if ( Parse_Pass != PASS_1 )
        return( SetCurrSeg( i, tokenarray ) );

    if( i != 1 ) {
        EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
        return( ERROR );
    }

    name = tokenarray[0].string_ptr;

    DebugMsg1(("SegmentDir(%s) enter: ModuleInfo.Ofssize=%u, num_seg=%u\n", name, ModuleInfo.Ofssize, ModuleInfo.g.num_segs ));

    /* See if the segment is already defined */
    sym = SymSearch( name );
    if( sym == NULL || sym->state == SYM_UNDEFINED ) {
        /* segment is not defined (yet) */
        sym = (struct asym *)CreateSegment( (struct dsym *)sym, name, TRUE );
        sym->list = TRUE; /* always list segments */
        dir = (struct dsym *)sym;
        dir->e.seginfo->seg_idx = ++ModuleInfo.g.num_segs;
        is_old = FALSE;
        /*
         * initialize segment with values from the one without suffix
         */
#if COFF_SUPPORT || ELF_SUPPORT
        if (Options.output_format == OFORMAT_COFF
#if ELF_SUPPORT
            || Options.output_format == OFORMAT_ELF
#endif
           ) {
            char *p;
            if ( p = strchr(sym->name, '$') ) {
                char buffer[MAX_ID_LEN+1];
                struct dsym *dir2;
                memcpy(buffer, sym->name, p - sym->name);
                buffer[p - sym->name] = NULLC;
                if ((dir2 = (struct dsym *)SymSearch(buffer)) && dir2->sym.state == SYM_SEG) {
                    dir->e.seginfo->readonly = dir2->e.seginfo->readonly;
                    dir->e.seginfo->segtype  = dir2->e.seginfo->segtype;
                    dir->e.seginfo->Ofssize  = dir2->e.seginfo->Ofssize;
                    dir->e.seginfo->alignment= dir2->e.seginfo->alignment;
                    dir->e.seginfo->characteristics = dir2->e.seginfo->characteristics;
                    dir->e.seginfo->combine         = dir2->e.seginfo->combine;
                    dir->e.seginfo->class_name_idx  = dir2->e.seginfo->class_name_idx;
                }
            }
        }
#endif
    } else if ( sym->state == SYM_SEG ) {
        /* segment already defined */
        dir = (struct dsym *)sym;
        is_old = TRUE;
        oldreadonly = dir->e.seginfo->readonly;
        //oldsegtype  = dir->e.seginfo->segtype;
        oldOfssize  = dir->e.seginfo->Ofssize;
        oldalign    = dir->e.seginfo->alignment;
        oldcharacteristics = dir->e.seginfo->characteristics;
        oldcombine  = dir->e.seginfo->combine;
        oldclassidx = dir->e.seginfo->class_name_idx;
        if( dir->e.seginfo->lname_idx == 0 ) {
            /* segment was mentioned in a group statement, but not really set up */
            is_old = FALSE;
            /* the segment list is to be sorted.
             * So unlink the segment and add it at the end.
             */
            UnlinkSeg( dir );
            dir->e.seginfo->seg_idx = ++ModuleInfo.g.num_segs;
            dir->next = NULL;
            if ( SymTables[TAB_SEG].head == NULL )
                SymTables[TAB_SEG].head = SymTables[TAB_SEG].tail = dir;
            else {
                SymTables[TAB_SEG].tail->next = dir;
                SymTables[TAB_SEG].tail = dir;
            }
        }
    } else {
        /* symbol is different kind, error */
        DebugMsg(("SegmentDir(%s): symbol redefinition\n", name ));
        EmitErr( SYMBOL_REDEFINITION, name );
        return( ERROR );
    }

    i++; /* go past SEGMENT */

    for( ; i < Token_Count; i++ ) {
        token = tokenarray[i].string_ptr;
        DebugMsg1(("SegmentDir(%s): i=%u, string=%s token=%X\n", name, i, token, tokenarray[i].token ));
        if( tokenarray[i].token == T_STRING ) {

            /* the class name - the only token which is of type STRING */
            /* string must be delimited by [double]quotes */
            if ( tokenarray[i].string_delim != '"' &&
                tokenarray[i].string_delim != '\'' ) {
                EmitErr( SYNTAX_ERROR_EX, token );
                continue;
            }
            /* remove the quote delimiters */
            token++;
            *(token+tokenarray[i].stringlen) = NULLC;

            SetSegmentClass( &dir->sym, token );

            DebugMsg1(("SegmentDir(%s): class found: %s\n", name, token ));
            continue;
        }

        /* check the rest of segment attributes.
         */
        typeidx = FindToken( token, SegAttrToken, sizeof( SegAttrToken )/sizeof( SegAttrToken[0] ) );
        if( typeidx < 0 ) {
            EmitErr( UNKNOWN_SEGMENT_ATTRIBUTE, token );
            continue;
        }
        type = &SegAttrValue[typeidx];

        /* initstate is used to check if any field is already
         * initialized
         */
        if( initstate & INIT_EXCL_MASK & type->init ) {
            EmitErr( SEGMENT_ATTRIBUTE_DEFINED_ALREADY, token );
            continue;
        } else {
            initstate |= type->init; /* mark it initialized */
        }

        switch ( type->init ) {
        case INIT_ATTR:
            dir->e.seginfo->readonly = TRUE;
            break;
        case INIT_ALIGN:
            DebugMsg1(("SegmentDir(%s): align attribute found\n", name ));
            dir->e.seginfo->alignment = type->value;
            break;
        case INIT_ALIGN_PARAM:
            DebugMsg1(("SegmentDir(%s): ALIGN() found\n", name ));
            if ( Options.output_format == OFORMAT_OMF ) {
                EmitErr( NOT_SUPPORTED_WITH_OMF_FORMAT, tokenarray[i].string_ptr );
                i = Token_Count; /* stop further parsing of this line */
                break;
            }
            i++;
            if ( tokenarray[i].token != T_OP_BRACKET ) {
                EmitErr( EXPECTED, "(" );
                break;
            }
            i++;
            if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR )
                break;
            if ( tokenarray[i].token != T_CL_BRACKET ) {
                EmitErr( EXPECTED, ")" );
                break;
            }
            if ( opndx.kind != EXPR_CONST ) {
                EmitError( CONSTANT_EXPECTED );
                break;
            }
            /*
             COFF allows alignment values
             1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192
             */
            for( temp = 1, temp2 = 0; temp < opndx.value && temp < 8192 ; temp <<= 1, temp2++ );
            if( temp != opndx.value ) {
                EmitError( POWER_OF_2 );
            }
            dir->e.seginfo->alignment = temp2;
            break;
        case INIT_COMBINE:
            DebugMsg1(("SegmentDir(%s): combine attribute found\n", name ));
            dir->e.seginfo->combine = type->value;
            break;
        case INIT_COMBINE_AT:
            DebugMsg1(("SegmentDir(%s): AT found\n", name ));
            dir->e.seginfo->combine = type->value;
            /* v2.05: always use MAX_SEGALIGNMENT */
            //dir->e.seginfo->alignment = -1;
            dir->e.seginfo->alignment = MAX_SEGALIGNMENT;
            i++;
            if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) != ERROR ) {
                if ( opndx.kind == EXPR_CONST ) {
                    dir->e.seginfo->abs_frame = opndx.value;
                    dir->e.seginfo->abs_offset = 0;
                } else {
                    EmitError( CONSTANT_EXPECTED );
                }
            }
            break;
#if COMDATSUPP
        case INIT_COMBINE_COMDAT:
            DebugMsg1(("SegmentDir(%s): COMDAT found\n", name ));
            if ( Options.output_format != OFORMAT_COFF ) {
                EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr );
                i = Token_Count; /* stop further parsing of this line */
                break;
            }
            i++;
            if ( tokenarray[i].token != T_OP_BRACKET ) {
                EmitErr( EXPECTED, "(" );
                break;
            }
            i++;
            if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR )
                break;
            if ( opndx.kind != EXPR_CONST ) {
                EmitError( CONSTANT_EXPECTED );
                i = Token_Count; /* stop further parsing of this line */
                break;
            }
            if ( opndx.value < 1 || opndx.value > 6 ) {
                EmitErr( VALUE_NOT_WITHIN_ALLOWED_RANGE, "1-6" );
            } else {
                /* if value is IMAGE_COMDAT_SELECT_ASSOCIATIVE,
                 * get the associated segment name argument.
                 */
                if ( opndx.value == 5 ) {
                    struct asym *sym2;
                    if ( tokenarray[i].token != T_COMMA ) {
                        EmitError( EXPECTING_COMMA );
                        i = Token_Count; /* stop further parsing of this line */
                        break;
                    }
                    i++;
                    if ( tokenarray[i].token != T_ID ) {
                        EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr );
                        i = Token_Count; /* stop further parsing of this line */
                        break;
                    }
                    /* associated segment must be COMDAT, but not associative */
                    sym2 = SymSearch( tokenarray[i].string_ptr );
                    if ( sym2 == NULL ||
                        sym2->state != SYM_SEG ||
                        ((struct dsym *)sym2)->e.seginfo->comdat_selection == 0 ||
                        ((struct dsym *)sym2)->e.seginfo->comdat_selection == 5 )
                        EmitErr( INVALID_ASSOCIATED_SEGMENT, tokenarray[i].string_ptr );
                    else
                        dir->e.seginfo->comdat_number = ((struct dsym *)sym2)->e.seginfo->seg_idx;
                    i++;
                }
            }
            if ( tokenarray[i].token != T_CL_BRACKET ) {
                EmitErr( EXPECTED, ")" );
                break;
            }
            dir->e.seginfo->comdat_selection = opndx.value;
            dir->e.seginfo->combine = type->value;
            break;
#endif
        case INIT_OFSSIZE:
        case INIT_OFSSIZE_FLAT:
            /* v2.07: check for compatible cpu mode */
            if ( type->value == USE32 && ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_386 )
#if AMD64_SUPPORT
                || type->value == USE64 && ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_64 )
#endif
               ) {
                EmitError( INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE );
                break;
            }
            if ( type->init == INIT_OFSSIZE_FLAT ) {
                DefineFlatGroup();
#if AMD64_SUPPORT
                dir->e.seginfo->Ofssize = ModuleInfo.defOfssize;
#else
                dir->e.seginfo->Ofssize = USE32;
#endif
                /* put the segment into the FLAT group.
                 * this is not quite Masm-compatible, because trying to put
                 * the segment into another group will cause an error.
                 */
                dir->e.seginfo->group = &ModuleInfo.flat_grp->sym;
            } else
                dir->e.seginfo->Ofssize = type->value;
            break;
#if COFF_SUPPORT || ELF_SUPPORT
        case INIT_CHAR_INFO:
            dir->e.seginfo->info = TRUE;
            break;
        case INIT_CHAR:
            DebugMsg1(("SegmentDir(%s): characteristics found\n", name ));
            ; /* characteristics are restricted to COFF/ELF */
            if ( Options.output_format == OFORMAT_OMF || Options.output_format == OFORMAT_BIN ) {
                EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr );
            } else
                dir->e.seginfo->characteristics |= type->value;
            break;
        case INIT_ALIAS:
            DebugMsg1(("SegmentDir(%s): ALIAS found\n", name ));
            if ( Options.output_format != OFORMAT_COFF &&
                Options.output_format != OFORMAT_ELF ) {
                EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr );
                i = Token_Count; /* stop further parsing of this line */
                break;
            }
            i++;
            if ( tokenarray[i].token != T_OP_BRACKET ) {
                EmitErr( EXPECTED, "(" );
                break;
            }
            i++;
            if ( tokenarray[i].token != T_STRING ||
                ( tokenarray[i].string_delim != '"' &&
                tokenarray[i].string_delim != '\'' ) ) {
                EmitErr( SYNTAX_ERROR_EX, token );
                i = Token_Count; /* stop further parsing of this line */
                break;
            }
            temp = i;
            i++;
            if ( tokenarray[i].token != T_CL_BRACKET ) {
                EmitErr( EXPECTED, ")" );
                break;
            }
            dir->e.seginfo->aliasname = LclAlloc( tokenarray[temp].stringlen );
            memcpy( dir->e.seginfo->aliasname, tokenarray[temp].string_ptr+1, tokenarray[temp].stringlen );
            *(dir->e.seginfo->aliasname+tokenarray[temp].stringlen) = NULLC;
            break;
#endif
#ifdef DEBUG_OUT
        default: /* shouldn't happen */
            myassert( 0 );
            break;
#endif
        }
    } /* end for */

    /* make a guess about the segment's type */
    if( dir->e.seginfo->segtype != SEGTYPE_CODE ) {
        enum seg_type res;

        token = GetLname( dir->e.seginfo->class_name_idx );
        res = TypeFromClassName( dir, token );
        if( res != SEGTYPE_UNDEF ) {
            dir->e.seginfo->segtype = res;
        }
#if 0 /* v2.03: removed */
        else {
            res = TypeFromSegmentName( name );
            dir->e.seginfo->segtype = res;
        }
#endif
    }

    if( is_old ) {
        int txt = 0;

        /* Check if new definition is different from previous one */

        // oldobj = dir->e.seginfo->segrec;
        if(  oldreadonly      != dir->e.seginfo->readonly )
            txt = TXT_READONLY;
        else if ( oldalign    != dir->e.seginfo->alignment )
            txt = TXT_ALIGNMENT;
        else if ( oldcombine  != dir->e.seginfo->combine )
            txt = TXT_COMBINE;
        else if ( oldOfssize  != dir->e.seginfo->Ofssize )
            txt = TXT_SEG_WORD_SIZE;
        else if ( oldclassidx != dir->e.seginfo->class_name_idx )
            txt = TXT_CLASS; /* Masm warns only! */
        else if ( oldcharacteristics != dir->e.seginfo->characteristics )
            txt = TXT_CHARACTERISTICS;

        if ( txt ) {
            EmitErr( SEGDEF_CHANGED, dir->sym.name, MsgGetEx( txt ) );
            //return( ERROR ); /* v2: display error, but continue */
        }

    } else {
        /* A new definition */

        sym = &dir->sym;
        sym->isdefined = TRUE;
        sym->segment = sym;
        sym->offset = 0;
        if( dir->e.seginfo->lname_idx == 0 ) {
            dir->e.seginfo->lname_idx = ++LnamesIdx;
            AddLnameData( sym );
        }

    }
    push_seg( dir ); /* set CurrSeg */

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

    return( SetOfssize() );
}