Beispiel #1
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 ));
}
Beispiel #2
0
void PutMsg( FILE *fp, int severity, int msgnum, va_list args )
/********************************************************************/
{
    int             i,j;
    char           *type;
    char            msgbuf[MAXMSGSIZE];
    char            buffer[MAX_LINE_LEN];

    if( fp != NULL ) {

        MsgGet( msgnum, msgbuf );
        switch (severity ) {
        case 1:  type = MsgGetEx( MSG_FATAL_PREFIX );   break;
        case 2:  type = MsgGetEx( MSG_ERROR_PREFIX );   break;
        case 4:  type = MsgGetEx( MSG_WARNING_PREFIX ); break;
        default:  type = NULL; i = 0; break;
        }
        if ( type )
            i = sprintf( buffer, "%s A%4u: ", type, severity * 1000 + msgnum );
        i += vsprintf( buffer+i, msgbuf, args );
        //buffer[i] = NULLC;

        if ( severity && (j = GetCurrSrcPos( msgbuf ))) {
            fwrite( msgbuf, 1, j, fp );
        } else
            j = 0;
        fwrite( buffer, 1, i, fp );
        fwrite( "\n", 1, 1, fp );

        /* if in Pass 1, add the error msg to the listing */
        if ( FileInfo.file[LST] &&
             severity &&
             Parse_Pass == PASS_1 &&
             fp == FileInfo.file[ERR] ) {
            LstWrite( LSTTYPE_DIRECTIVE, GetCurrOffset(), 0 );
            LstPrintf( "                           %s", buffer );
            LstNL();
        }
    }
}
Beispiel #3
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
void SetSymSegOfs( struct asym *sym )
/***********************************/
{
    sym->segment = &CurrSeg->sym;
    sym->offset = GetCurrOffset();
}
Beispiel #6
0
ret_code HllEndDef( int i )
/*************************/
{
    //struct asm_sym      *sym;
    struct hll_list     *hll;
    int                 cmd = AsmBuffer[i]->value;
    char                buffer[MAX_ID_LEN+1+64];
    
    DebugMsg(("HllEndDef(%s) enter\n", AsmBuffer[i]->string_ptr ));

    if ( HllStack == NULL ) {
        DebugMsg(("HllEndDef: hll stack is empty\n"));
        AsmError( DIRECTIVE_MUST_BE_IN_CONTROL_BLOCK );
        return( ERROR );
    }

    hll = HllStack;
    HllStack = hll->next;


    PushLineQueue();

    switch (cmd) {
    case T_DOT_ENDIF:
        if ( hll->cmd != HLL_IF ) {
            DebugMsg(("HllEndDef no .IF on the hll stack\n"));
            AsmErr( BLOCK_NESTING_ERROR, AsmBuffer[i]->string_ptr );
            return( ERROR );
        }
        /* if a test label isn't created yet, create it */
        if ( hll->symtest ) {
            MakeLabel( buffer, hll->symtest );
            AddLineQueue( buffer );
        }
        /* create the exit label if it exists */
        if ( hll->symexit ) {
            MakeLabel( buffer, hll->symexit );
            AddLineQueue( buffer );
        }
        i++;
        break;
    case T_DOT_ENDW:
        if ( hll->cmd != HLL_WHILE ) {
            DebugMsg(("HllEndDef no .WHILE on the hll stack\n"));
            AsmErr( BLOCK_NESTING_ERROR, AsmBuffer[i]->string_ptr );
            return( ERROR );
        }
        /* create test label  */
        if ( hll->symtest ) {
            MakeLabel( buffer, hll->symtest );
            DebugMsg(("HllEndDef: created: %s\n", buffer));
            AddLineQueue( buffer );
        }
        HllPushTestLines( hll );

        MakeLabel( buffer, hll->symexit );
        AddLineQueue( buffer );
        i++;
        break;
    case T_DOT_UNTILCXZ:
        if ( hll->cmd != HLL_REPEAT ) {
            DebugMsg(("HllEndDef no .REPEAT on the hll stack\n"));
            AsmErr( BLOCK_NESTING_ERROR, AsmBuffer[i]->string_ptr );
            return( ERROR );
        }
        MakeLabel( buffer, hll->symtest );
        AddLineQueue( buffer );

        i++;
        /* read in optional (simple) expression */
        if ( AsmBuffer[i]->token != T_FINAL ) {
            if ( ERROR == EvaluateHllExpression( hll, &i, LABELFIRST, FALSE ) ) {
                return( ERROR );
            }
            if ( HllCheckTestLines(hll) == ERROR ) {
                AsmError( EXPR_TOO_COMPLEX_FOR_UNTILCXZ );
                return( ERROR );
            }
            /* write condition lines */
            HllPushTestLines( hll );
        } else {
            sprintf( buffer, " loop %s", hll->symfirst );
            AddLineQueue( buffer );
        }
        MakeLabel( buffer, hll->symexit );
        AddLineQueue( buffer );
        break;
    case T_DOT_UNTIL:
        if ( hll->cmd != HLL_REPEAT ) {
            DebugMsg(("HllEndDef no .REPEAT on the hll stack\n"));
            AsmErr( BLOCK_NESTING_ERROR, AsmBuffer[i]->string_ptr );
            return( ERROR );
        }
        MakeLabel( buffer, hll->symtest );
        AddLineQueue( buffer );

        i++;
        /* read in (optional) expression */
        /* if expression is missing, just generate nothing */
        if ( AsmBuffer[i]->token != T_FINAL ) {
            if ( ERROR == EvaluateHllExpression( hll, &i, LABELFIRST, FALSE ) ) {
                return( ERROR );
            }
            /* write condition lines */
            HllPushTestLines( hll );
        }
#if 0
        sprintf( buffer, " jmp %s", hll->symfirst );
        AddLineQueue( buffer );
#endif

        MakeLabel( buffer, hll->symexit );
        AddLineQueue( buffer );
        break;
    }

    AsmFree( hll->symfirst );
    AsmFree( hll->symtest );
    AsmFree( hll->symexit );
    AsmFree( hll->condlines );
    AsmFree( hll );

    if ( AsmBuffer[i]->token != T_FINAL ) {
        AsmErr( SYNTAX_ERROR_EX, AsmBuffer[i]->string_ptr );
        return( ERROR );
    }

    if ( ModuleInfo.list )
        LstWrite( LSTTYPE_DIRECTIVE, GetCurrOffset(), NULL );

    if ( line_queue )
        RunLineQueue();

    return( NOT_ERROR );
}
Beispiel #7
0
ret_code HllStartDef( int i )
/***************************/
{
    struct hll_list      *hll;
    int                  cmd = AsmBuffer[i]->value;
    char                 buffer[MAX_ID_LEN+1+64];

    DebugMsg(("HllStartDef(%u [=%s]) enter\n", i, AsmBuffer[i]->string_ptr ));

#if FASTPASS
    /* make sure the directive is stored */
    if ( StoreState == FALSE && Parse_Pass == PASS_1 ) {
        SaveState();
    }
#endif

    switch (cmd) {
    case T_DOT_REPEAT:
        if ( AsmBuffer[i+1]->token != T_FINAL ) {
            DebugMsg(("HllStartDef: unexpected tokens behind .REPEAT\n" ));
            AsmError( SYNTAX_ERROR );
            return( ERROR );
        }
        break;
    case T_DOT_IF:
    case T_DOT_WHILE:
#if 0 /* Masm allows a missing expression! */
        if ( AsmBuffer[i+1]->token == T_FINAL ) {
            AsmError( SYNTAX_ERROR );
            return( ERROR );
        }
#endif
        break;
    }
    hll = AsmAlloc( sizeof(hll_list) );

    hll->cmd = HLL_UNDEF;

    /* create labels which are always needed */
    /* for .IF -.ENDIF without .ELSE no symexit label is needed. */

    hll->symfirst = NULL;
    hll->symexit = NULL;
    hll->symtest = MakeAnonymousLabel();

    hll->condlines = NULL;

    // structure for .IF .ELSE .ENDIF
    //    cond jump to symtest
    //    ...
    //    jmp symexit
    //  symtest:
    //    ...
    //  symexit:

    // structure for .IF .ELSEIF
    //    cond jump to symtest
    //    ...
    //    jmp symexit
    //  symtest:
    //    cond jump to (new) symtest
    //    ...
    //    jmp symexit
    //  symtest:
    //    ...

    // structure for .WHILE and .REPEAT:
    //   jmp symtest (for .WHILE only)
    // symfirst:
    //   ...
    // symtest: (jumped to by .continue)
    //   test end condition, cond jump to symfirst
    // symexit: (jumped to by .break)

    PushLineQueue();

    switch (cmd) {
    case T_DOT_IF:
        hll->cmd = HLL_IF;
        /* get the C-style expression, convert to ASM code lines */
        i++;
        if ( ERROR == EvaluateHllExpression( hll, &i, LABELTEST, FALSE ) ) {
            return( ERROR );
        }
        HllPushTestLines( hll );
#if 1
        /* if no lines have been created, the symtest label isn't needed */
        if ( line_queue == NULL ) {
            AsmFree( hll->symtest );
            hll->symtest = NULL;
        }
#endif
        break;
    case T_DOT_WHILE:
    case T_DOT_REPEAT:
        /* create the label to loop start */
        hll->symfirst = MakeAnonymousLabel();
        hll->symexit = MakeAnonymousLabel();
        if ( cmd == T_DOT_WHILE ) {
            i++;
            hll->cmd = HLL_WHILE;
            if ( AsmBuffer[i]->token != T_FINAL ) {
                if ( ERROR == EvaluateHllExpression( hll, &i, LABELFIRST, TRUE ) ) {
                    return( ERROR );
                }
            } else
                hll->condlines = "";
            /* create a jump to second label */
            /* optimisation: if second label is just a jump, dont jump! */
            if ( hll->condlines && _memicmp(hll->condlines, "jmp", 3) ) {
                sprintf( buffer, " jmp %s", hll->symtest );
                AddLineQueue( buffer );
            } else {
                AsmFree( hll->symtest );
                hll->symtest = NULL;
            }
        } else {
            i++;
            hll->cmd = HLL_REPEAT;
        }
        MakeLabel( buffer, hll->symfirst );
        AddLineQueue( buffer );
        break;
    }
    if ( AsmBuffer[i]->token != T_FINAL ) {
        DebugMsg(("HllStartDef: unexpected token %u [%s]\n", AsmBuffer[i]->token, AsmBuffer[i]->string_ptr ));
        AsmErr( SYNTAX_ERROR_EX, AsmBuffer[i]->string_ptr );
        return( ERROR );
    }
    hll->next = HllStack;
    HllStack = hll;

    if ( ModuleInfo.list )
        LstWrite( LSTTYPE_DIRECTIVE, GetCurrOffset(), NULL );

    if ( line_queue ) /* might be NULL! (".if 1") */
        RunLineQueue();

    return( NOT_ERROR );
}
Beispiel #8
0
ret_code HllExitDef( int i )
/**************************/
{
    //int                 level;
    //struct asm_sym      *sym;
    struct hll_list     *hll;
    char                *savedlines;
    hll_cmd             savedcmd;
    int                 cmd = AsmBuffer[i]->value;
    char                buffer[MAX_ID_LEN+1+64];

    DebugMsg(("HllExitDef(%s) enter\n", AsmBuffer[i]->string_ptr ));

    hll = HllStack;

    if ( hll == NULL ) {
        DebugMsg(("HllExitDef stack error\n"));
        AsmError( DIRECTIVE_MUST_BE_IN_CONTROL_BLOCK );
        return( ERROR );
    }

    PushLineQueue();

    switch (cmd) {
    case T_DOT_ELSE:
    case T_DOT_ELSEIF:
        if ( hll->cmd != HLL_IF ) {
            DebugMsg(("HllExitDef(%s): symtest=%X\n", AsmBuffer[i]->string_ptr, hll->symtest));
            AsmErr( BLOCK_NESTING_ERROR, AsmBuffer[i]->string_ptr );
            return( ERROR );
        }
        /* the "symexit" label is only needed if an .ELSE branch exists.
         That's why it is created delayed.
         */
        if ( hll->symexit == NULL)
            hll->symexit = MakeAnonymousLabel();

        sprintf( buffer," jmp %s", hll->symexit );
        AddLineQueue( buffer );
        if ( hll->symtest ) {
            MakeLabel( buffer, hll->symtest );
            AddLineQueue( buffer );
            AsmFree( hll->symtest );
            hll->symtest = NULL;
        }
        i++;
        if (cmd == T_DOT_ELSEIF) {
            /* create new symtest label */
            hll->symtest = MakeAnonymousLabel();
            if ( ERROR == EvaluateHllExpression( hll, &i, LABELTEST, FALSE ) ) {
                return( ERROR );
            }
            HllPushTestLines( hll );
        }
        break;
    case T_DOT_BREAK:
    case T_DOT_CONTINUE:
        for ( ; hll && hll->cmd == HLL_IF; hll = hll->next );
        if ( hll == NULL ) {
            AsmError( DIRECTIVE_MUST_BE_IN_CONTROL_BLOCK );
            return( ERROR );
        }
        /* .BREAK .IF ... or .CONTINUE .IF ? */
        i++;
        if ( AsmBuffer[i]->token != T_FINAL ) {
            if ( AsmBuffer[i]->token == T_DIRECTIVE && AsmBuffer[i]->value == T_DOT_IF ) {
                savedlines = hll->condlines;
                savedcmd = hll->cmd;
                hll->condlines = NULL;
                hll->cmd = HLL_BREAK;
                i++;
                if ( cmd == T_DOT_BREAK ) {
                    if ( ERROR == EvaluateHllExpression( hll, &i, LABELEXIT, TRUE ) ) {
                        return( ERROR );
                    }
                } else { /* T_DOT_CONTINUE */
                    if ( ERROR == EvaluateHllExpression( hll, &i, LABELTEST, TRUE ) ) {
                        return( ERROR );
                    }
                }
                HllPushTestLines( hll );
                AsmFree( hll->condlines );
                hll->condlines = savedlines;
                hll->cmd = savedcmd;
            }
        } else {
            if ( cmd == T_DOT_BREAK ) {
                sprintf( buffer," jmp %s", hll->symexit );
            } else {
                if ( hll->symtest )
                    sprintf( buffer," jmp %s", hll->symtest );
                else
                    sprintf( buffer," jmp %s", hll->symfirst );
            }
            AddLineQueue( buffer );
        }
        break;
    }
    if ( AsmBuffer[i]->token != T_FINAL ) {
        AsmErr( SYNTAX_ERROR_EX, AsmBuffer[i]->string_ptr );
        return( ERROR );
    }

    if ( ModuleInfo.list )
        LstWrite( LSTTYPE_DIRECTIVE, GetCurrOffset(), NULL );

    RunLineQueue();

    return( NOT_ERROR );
}